aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/assoc.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/libertas/assoc.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/libertas/assoc.c')
-rw-r--r--drivers/net/wireless/libertas/assoc.c535
1 files changed, 457 insertions, 78 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index dd8732611ba9..12a2ef9dacea 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -4,6 +4,7 @@
4#include <linux/etherdevice.h> 4#include <linux/etherdevice.h>
5#include <linux/ieee80211.h> 5#include <linux/ieee80211.h>
6#include <linux/if_arp.h> 6#include <linux/if_arp.h>
7#include <linux/slab.h>
7#include <net/lib80211.h> 8#include <net/lib80211.h>
8 9
9#include "assoc.h" 10#include "assoc.h"
@@ -23,6 +24,13 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
23 */ 24 */
24#define CAPINFO_MASK (~(0xda00)) 25#define CAPINFO_MASK (~(0xda00))
25 26
27/**
28 * 802.11b/g supported bitrates (in 500Kb/s units)
29 */
30u8 lbs_bg_rates[MAX_RATES] =
31 { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
320x00, 0x00 };
33
26 34
27/** 35/**
28 * @brief This function finds common rates between rates and card rates. 36 * @brief This function finds common rates between rates and card rates.
@@ -147,6 +155,395 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth
147} 155}
148 156
149 157
158int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
159 struct assoc_request *assoc)
160{
161 struct cmd_ds_802_11_set_wep cmd;
162 int ret = 0;
163
164 lbs_deb_enter(LBS_DEB_CMD);
165
166 memset(&cmd, 0, sizeof(cmd));
167 cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
168 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
169
170 cmd.action = cpu_to_le16(cmd_action);
171
172 if (cmd_action == CMD_ACT_ADD) {
173 int i;
174
175 /* default tx key index */
176 cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
177 CMD_WEP_KEY_INDEX_MASK);
178
179 /* Copy key types and material to host command structure */
180 for (i = 0; i < 4; i++) {
181 struct enc_key *pkey = &assoc->wep_keys[i];
182
183 switch (pkey->len) {
184 case KEY_LEN_WEP_40:
185 cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
186 memmove(cmd.keymaterial[i], pkey->key, pkey->len);
187 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
188 break;
189 case KEY_LEN_WEP_104:
190 cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
191 memmove(cmd.keymaterial[i], pkey->key, pkey->len);
192 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
193 break;
194 case 0:
195 break;
196 default:
197 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
198 i, pkey->len);
199 ret = -1;
200 goto done;
201 break;
202 }
203 }
204 } else if (cmd_action == CMD_ACT_REMOVE) {
205 /* ACT_REMOVE clears _all_ WEP keys */
206
207 /* default tx key index */
208 cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
209 CMD_WEP_KEY_INDEX_MASK);
210 lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
211 }
212
213 ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
214done:
215 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
216 return ret;
217}
218
219int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
220 uint16_t *enable)
221{
222 struct cmd_ds_802_11_enable_rsn cmd;
223 int ret;
224
225 lbs_deb_enter(LBS_DEB_CMD);
226
227 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
228 cmd.action = cpu_to_le16(cmd_action);
229
230 if (cmd_action == CMD_ACT_GET)
231 cmd.enable = 0;
232 else {
233 if (*enable)
234 cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
235 else
236 cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
237 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
238 }
239
240 ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
241 if (!ret && cmd_action == CMD_ACT_GET)
242 *enable = le16_to_cpu(cmd.enable);
243
244 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
245 return ret;
246}
247
248static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
249 struct enc_key *key)
250{
251 lbs_deb_enter(LBS_DEB_CMD);
252
253 if (key->flags & KEY_INFO_WPA_ENABLED)
254 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
255 if (key->flags & KEY_INFO_WPA_UNICAST)
256 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
257 if (key->flags & KEY_INFO_WPA_MCAST)
258 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
259
260 keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
261 keyparam->keytypeid = cpu_to_le16(key->type);
262 keyparam->keylen = cpu_to_le16(key->len);
263 memcpy(keyparam->key, key->key, key->len);
264
265 /* Length field doesn't include the {type,length} header */
266 keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
267 lbs_deb_leave(LBS_DEB_CMD);
268}
269
270int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
271 struct assoc_request *assoc)
272{
273 struct cmd_ds_802_11_key_material cmd;
274 int ret = 0;
275 int index = 0;
276
277 lbs_deb_enter(LBS_DEB_CMD);
278
279 cmd.action = cpu_to_le16(cmd_action);
280 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
281
282 if (cmd_action == CMD_ACT_GET) {
283 cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2);
284 } else {
285 memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
286
287 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
288 set_one_wpa_key(&cmd.keyParamSet[index],
289 &assoc->wpa_unicast_key);
290 index++;
291 }
292
293 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
294 set_one_wpa_key(&cmd.keyParamSet[index],
295 &assoc->wpa_mcast_key);
296 index++;
297 }
298
299 /* The common header and as many keys as we included */
300 cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
301 keyParamSet[index]));
302 }
303 ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
304 /* Copy the returned key to driver private data */
305 if (!ret && cmd_action == CMD_ACT_GET) {
306 void *buf_ptr = cmd.keyParamSet;
307 void *resp_end = &(&cmd)[1];
308
309 while (buf_ptr < resp_end) {
310 struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
311 struct enc_key *key;
312 uint16_t param_set_len = le16_to_cpu(keyparam->length);
313 uint16_t key_len = le16_to_cpu(keyparam->keylen);
314 uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
315 uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
316 void *end;
317
318 end = (void *)keyparam + sizeof(keyparam->type)
319 + sizeof(keyparam->length) + param_set_len;
320
321 /* Make sure we don't access past the end of the IEs */
322 if (end > resp_end)
323 break;
324
325 if (key_flags & KEY_INFO_WPA_UNICAST)
326 key = &priv->wpa_unicast_key;
327 else if (key_flags & KEY_INFO_WPA_MCAST)
328 key = &priv->wpa_mcast_key;
329 else
330 break;
331
332 /* Copy returned key into driver */
333 memset(key, 0, sizeof(struct enc_key));
334 if (key_len > sizeof(key->key))
335 break;
336 key->type = key_type;
337 key->flags = key_flags;
338 key->len = key_len;
339 memcpy(key->key, keyparam->key, key->len);
340
341 buf_ptr = end + 1;
342 }
343 }
344
345 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
346 return ret;
347}
348
349static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
350{
351/* Bit Rate
352* 15:13 Reserved
353* 12 54 Mbps
354* 11 48 Mbps
355* 10 36 Mbps
356* 9 24 Mbps
357* 8 18 Mbps
358* 7 12 Mbps
359* 6 9 Mbps
360* 5 6 Mbps
361* 4 Reserved
362* 3 11 Mbps
363* 2 5.5 Mbps
364* 1 2 Mbps
365* 0 1 Mbps
366**/
367
368 uint16_t ratemask;
369 int i = lbs_data_rate_to_fw_index(rate);
370 if (lower_rates_ok)
371 ratemask = (0x1fef >> (12 - i));
372 else
373 ratemask = (1 << i);
374 return cpu_to_le16(ratemask);
375}
376
377int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
378 uint16_t cmd_action)
379{
380 struct cmd_ds_802_11_rate_adapt_rateset cmd;
381 int ret;
382
383 lbs_deb_enter(LBS_DEB_CMD);
384
385 if (!priv->cur_rate && !priv->enablehwauto)
386 return -EINVAL;
387
388 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
389
390 cmd.action = cpu_to_le16(cmd_action);
391 cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
392 cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
393 ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
394 if (!ret && cmd_action == CMD_ACT_GET)
395 priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
396
397 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
398 return ret;
399}
400
401/**
402 * @brief Set the data rate
403 *
404 * @param priv A pointer to struct lbs_private structure
405 * @param rate The desired data rate, or 0 to clear a locked rate
406 *
407 * @return 0 on success, error on failure
408 */
409int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
410{
411 struct cmd_ds_802_11_data_rate cmd;
412 int ret = 0;
413
414 lbs_deb_enter(LBS_DEB_CMD);
415
416 memset(&cmd, 0, sizeof(cmd));
417 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
418
419 if (rate > 0) {
420 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
421 cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
422 if (cmd.rates[0] == 0) {
423 lbs_deb_cmd("DATA_RATE: invalid requested rate of"
424 " 0x%02X\n", rate);
425 ret = 0;
426 goto out;
427 }
428 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
429 } else {
430 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
431 lbs_deb_cmd("DATA_RATE: setting auto\n");
432 }
433
434 ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
435 if (ret)
436 goto out;
437
438 lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd));
439
440 /* FIXME: get actual rates FW can do if this command actually returns
441 * all data rates supported.
442 */
443 priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
444 lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
445
446out:
447 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
448 return ret;
449}
450
451
452int lbs_cmd_802_11_rssi(struct lbs_private *priv,
453 struct cmd_ds_command *cmd)
454{
455
456 lbs_deb_enter(LBS_DEB_CMD);
457 cmd->command = cpu_to_le16(CMD_802_11_RSSI);
458 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) +
459 sizeof(struct cmd_header));
460 cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
461
462 /* reset Beacon SNR/NF/RSSI values */
463 priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
464 priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
465 priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
466 priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
467 priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
468 priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
469
470 lbs_deb_leave(LBS_DEB_CMD);
471 return 0;
472}
473
474int lbs_ret_802_11_rssi(struct lbs_private *priv,
475 struct cmd_ds_command *resp)
476{
477 struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
478
479 lbs_deb_enter(LBS_DEB_CMD);
480
481 /* store the non average value */
482 priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
483 priv->NF[TYPE_BEACON][TYPE_NOAVG] =
484 get_unaligned_le16(&rssirsp->noisefloor);
485
486 priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
487 priv->NF[TYPE_BEACON][TYPE_AVG] =
488 get_unaligned_le16(&rssirsp->avgnoisefloor);
489
490 priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
491 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
492 priv->NF[TYPE_BEACON][TYPE_NOAVG]);
493
494 priv->RSSI[TYPE_BEACON][TYPE_AVG] =
495 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
496 priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
497
498 lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
499 priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
500 priv->RSSI[TYPE_BEACON][TYPE_AVG]);
501
502 lbs_deb_leave(LBS_DEB_CMD);
503 return 0;
504}
505
506
507int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
508 struct cmd_ds_command *cmd,
509 u16 cmd_action)
510{
511 struct cmd_ds_802_11_beacon_control
512 *bcn_ctrl = &cmd->params.bcn_ctrl;
513
514 lbs_deb_enter(LBS_DEB_CMD);
515 cmd->size =
516 cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
517 + sizeof(struct cmd_header));
518 cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
519
520 bcn_ctrl->action = cpu_to_le16(cmd_action);
521 bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
522 bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
523
524 lbs_deb_leave(LBS_DEB_CMD);
525 return 0;
526}
527
528int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
529 struct cmd_ds_command *resp)
530{
531 struct cmd_ds_802_11_beacon_control *bcn_ctrl =
532 &resp->params.bcn_ctrl;
533
534 lbs_deb_enter(LBS_DEB_CMD);
535
536 if (bcn_ctrl->action == CMD_ACT_GET) {
537 priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
538 priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
539 }
540
541 lbs_deb_enter(LBS_DEB_CMD);
542 return 0;
543}
544
545
546
150static int lbs_assoc_post(struct lbs_private *priv, 547static int lbs_assoc_post(struct lbs_private *priv,
151 struct cmd_ds_802_11_associate_response *resp) 548 struct cmd_ds_802_11_associate_response *resp)
152{ 549{
@@ -226,7 +623,7 @@ static int lbs_assoc_post(struct lbs_private *priv,
226 priv->connect_status = LBS_CONNECTED; 623 priv->connect_status = LBS_CONNECTED;
227 624
228 /* Update current SSID and BSSID */ 625 /* Update current SSID and BSSID */
229 memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); 626 memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
230 priv->curbssparams.ssid_len = bss->ssid_len; 627 priv->curbssparams.ssid_len = bss->ssid_len;
231 memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); 628 memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
232 629
@@ -369,12 +766,7 @@ static int lbs_associate(struct lbs_private *priv,
369 (u16)(pos - (u8 *) &cmd.iebuf)); 766 (u16)(pos - (u8 *) &cmd.iebuf));
370 767
371 /* update curbssparams */ 768 /* update curbssparams */
372 priv->curbssparams.channel = bss->phy.ds.channel; 769 priv->channel = bss->phy.ds.channel;
373
374 if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
375 ret = -1;
376 goto done;
377 }
378 770
379 ret = lbs_cmd_with_response(priv, command, &cmd); 771 ret = lbs_cmd_with_response(priv, command, &cmd);
380 if (ret == 0) { 772 if (ret == 0) {
@@ -414,8 +806,7 @@ static int lbs_try_associate(struct lbs_private *priv,
414 } 806 }
415 807
416 /* Use short preamble only when both the BSS and firmware support it */ 808 /* Use short preamble only when both the BSS and firmware support it */
417 if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && 809 if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
418 (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
419 preamble = RADIO_PREAMBLE_SHORT; 810 preamble = RADIO_PREAMBLE_SHORT;
420 811
421 ret = lbs_set_radio(priv, preamble, 1); 812 ret = lbs_set_radio(priv, preamble, 1);
@@ -472,7 +863,7 @@ static int lbs_adhoc_post(struct lbs_private *priv,
472 memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); 863 memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
473 864
474 /* Set the new SSID to current SSID */ 865 /* Set the new SSID to current SSID */
475 memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); 866 memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
476 priv->curbssparams.ssid_len = bss->ssid_len; 867 priv->curbssparams.ssid_len = bss->ssid_len;
477 868
478 netif_carrier_on(priv->dev); 869 netif_carrier_on(priv->dev);
@@ -487,7 +878,7 @@ static int lbs_adhoc_post(struct lbs_private *priv,
487 lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", 878 lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
488 print_ssid(ssid, bss->ssid, bss->ssid_len), 879 print_ssid(ssid, bss->ssid, bss->ssid_len),
489 priv->curbssparams.bssid, 880 priv->curbssparams.bssid,
490 priv->curbssparams.channel); 881 priv->channel);
491 882
492done: 883done:
493 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); 884 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
@@ -546,8 +937,7 @@ static int lbs_adhoc_join(struct lbs_private *priv,
546 } 937 }
547 938
548 /* Use short preamble only when both the BSS and firmware support it */ 939 /* Use short preamble only when both the BSS and firmware support it */
549 if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && 940 if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
550 (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
551 lbs_deb_join("AdhocJoin: Short preamble\n"); 941 lbs_deb_join("AdhocJoin: Short preamble\n");
552 preamble = RADIO_PREAMBLE_SHORT; 942 preamble = RADIO_PREAMBLE_SHORT;
553 } 943 }
@@ -560,7 +950,7 @@ static int lbs_adhoc_join(struct lbs_private *priv,
560 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); 950 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
561 951
562 priv->adhoccreate = 0; 952 priv->adhoccreate = 0;
563 priv->curbssparams.channel = bss->channel; 953 priv->channel = bss->channel;
564 954
565 /* Build the join command */ 955 /* Build the join command */
566 memset(&cmd, 0, sizeof(cmd)); 956 memset(&cmd, 0, sizeof(cmd));
@@ -633,11 +1023,6 @@ static int lbs_adhoc_join(struct lbs_private *priv,
633 } 1023 }
634 } 1024 }
635 1025
636 if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
637 ret = -1;
638 goto out;
639 }
640
641 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); 1026 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
642 if (ret == 0) { 1027 if (ret == 0) {
643 ret = lbs_adhoc_post(priv, 1028 ret = lbs_adhoc_post(priv,
@@ -661,7 +1046,7 @@ static int lbs_adhoc_start(struct lbs_private *priv,
661 struct assoc_request *assoc_req) 1046 struct assoc_request *assoc_req)
662{ 1047{
663 struct cmd_ds_802_11_ad_hoc_start cmd; 1048 struct cmd_ds_802_11_ad_hoc_start cmd;
664 u8 preamble = RADIO_PREAMBLE_LONG; 1049 u8 preamble = RADIO_PREAMBLE_SHORT;
665 size_t ratesize = 0; 1050 size_t ratesize = 0;
666 u16 tmpcap = 0; 1051 u16 tmpcap = 0;
667 int ret = 0; 1052 int ret = 0;
@@ -669,11 +1054,6 @@ static int lbs_adhoc_start(struct lbs_private *priv,
669 1054
670 lbs_deb_enter(LBS_DEB_ASSOC); 1055 lbs_deb_enter(LBS_DEB_ASSOC);
671 1056
672 if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
673 lbs_deb_join("ADHOC_START: Will use short preamble\n");
674 preamble = RADIO_PREAMBLE_SHORT;
675 }
676
677 ret = lbs_set_radio(priv, preamble, 1); 1057 ret = lbs_set_radio(priv, preamble, 1);
678 if (ret) 1058 if (ret)
679 goto out; 1059 goto out;
@@ -737,12 +1117,6 @@ static int lbs_adhoc_start(struct lbs_private *priv,
737 lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n", 1117 lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
738 cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]); 1118 cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
739 1119
740 if (lbs_create_dnld_countryinfo_11d(priv)) {
741 lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n");
742 ret = -1;
743 goto out;
744 }
745
746 lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n", 1120 lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
747 assoc_req->channel, assoc_req->band); 1121 assoc_req->channel, assoc_req->band);
748 1122
@@ -787,11 +1161,11 @@ int lbs_adhoc_stop(struct lbs_private *priv)
787static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, 1161static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
788 struct bss_descriptor *match_bss) 1162 struct bss_descriptor *match_bss)
789{ 1163{
790 if (!secinfo->wep_enabled && !secinfo->WPAenabled 1164 if (!secinfo->wep_enabled &&
791 && !secinfo->WPA2enabled 1165 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
792 && match_bss->wpa_ie[0] != WLAN_EID_GENERIC 1166 match_bss->wpa_ie[0] != WLAN_EID_GENERIC &&
793 && match_bss->rsn_ie[0] != WLAN_EID_RSN 1167 match_bss->rsn_ie[0] != WLAN_EID_RSN &&
794 && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) 1168 !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
795 return 1; 1169 return 1;
796 else 1170 else
797 return 0; 1171 return 0;
@@ -800,9 +1174,9 @@ static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
800static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, 1174static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
801 struct bss_descriptor *match_bss) 1175 struct bss_descriptor *match_bss)
802{ 1176{
803 if (secinfo->wep_enabled && !secinfo->WPAenabled 1177 if (secinfo->wep_enabled &&
804 && !secinfo->WPA2enabled 1178 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
805 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) 1179 (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
806 return 1; 1180 return 1;
807 else 1181 else
808 return 0; 1182 return 0;
@@ -811,8 +1185,8 @@ static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
811static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, 1185static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
812 struct bss_descriptor *match_bss) 1186 struct bss_descriptor *match_bss)
813{ 1187{
814 if (!secinfo->wep_enabled && secinfo->WPAenabled 1188 if (!secinfo->wep_enabled && secinfo->WPAenabled &&
815 && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) 1189 (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
816 /* privacy bit may NOT be set in some APs like LinkSys WRT54G 1190 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
817 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ 1191 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
818 ) 1192 )
@@ -837,11 +1211,11 @@ static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
837static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, 1211static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
838 struct bss_descriptor *match_bss) 1212 struct bss_descriptor *match_bss)
839{ 1213{
840 if (!secinfo->wep_enabled && !secinfo->WPAenabled 1214 if (!secinfo->wep_enabled &&
841 && !secinfo->WPA2enabled 1215 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
842 && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) 1216 (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) &&
843 && (match_bss->rsn_ie[0] != WLAN_EID_RSN) 1217 (match_bss->rsn_ie[0] != WLAN_EID_RSN) &&
844 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) 1218 (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
845 return 1; 1219 return 1;
846 else 1220 else
847 return 0; 1221 return 0;
@@ -1099,7 +1473,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
1099 /* else send START command */ 1473 /* else send START command */
1100 lbs_deb_assoc("SSID not found, creating adhoc network\n"); 1474 lbs_deb_assoc("SSID not found, creating adhoc network\n");
1101 memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, 1475 memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
1102 IW_ESSID_MAX_SIZE); 1476 IEEE80211_MAX_SSID_LEN);
1103 assoc_req->bss.ssid_len = assoc_req->ssid_len; 1477 assoc_req->bss.ssid_len = assoc_req->ssid_len;
1104 lbs_adhoc_start(priv, assoc_req); 1478 lbs_adhoc_start(priv, assoc_req);
1105 } 1479 }
@@ -1152,8 +1526,8 @@ static int assoc_helper_associate(struct lbs_private *priv,
1152 /* If we're given and 'any' BSSID, try associating based on SSID */ 1526 /* If we're given and 'any' BSSID, try associating based on SSID */
1153 1527
1154 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { 1528 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
1155 if (compare_ether_addr(bssid_any, assoc_req->bssid) 1529 if (compare_ether_addr(bssid_any, assoc_req->bssid) &&
1156 && compare_ether_addr(bssid_off, assoc_req->bssid)) { 1530 compare_ether_addr(bssid_off, assoc_req->bssid)) {
1157 ret = assoc_helper_bssid(priv, assoc_req); 1531 ret = assoc_helper_bssid(priv, assoc_req);
1158 done = 1; 1532 done = 1;
1159 } 1533 }
@@ -1185,7 +1559,8 @@ static int assoc_helper_mode(struct lbs_private *priv,
1185 } 1559 }
1186 1560
1187 priv->mode = assoc_req->mode; 1561 priv->mode = assoc_req->mode;
1188 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode); 1562 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE,
1563 assoc_req->mode == IW_MODE_ADHOC ? 2 : 1);
1189 1564
1190done: 1565done:
1191 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); 1566 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -1205,7 +1580,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
1205 goto done; 1580 goto done;
1206 } 1581 }
1207 1582
1208 if (assoc_req->channel == priv->curbssparams.channel) 1583 if (assoc_req->channel == priv->channel)
1209 goto done; 1584 goto done;
1210 1585
1211 if (priv->mesh_dev) { 1586 if (priv->mesh_dev) {
@@ -1217,7 +1592,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
1217 } 1592 }
1218 1593
1219 lbs_deb_assoc("ASSOC: channel: %d -> %d\n", 1594 lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
1220 priv->curbssparams.channel, assoc_req->channel); 1595 priv->channel, assoc_req->channel);
1221 1596
1222 ret = lbs_set_channel(priv, assoc_req->channel); 1597 ret = lbs_set_channel(priv, assoc_req->channel);
1223 if (ret < 0) 1598 if (ret < 0)
@@ -1232,17 +1607,15 @@ static int assoc_helper_channel(struct lbs_private *priv,
1232 goto done; 1607 goto done;
1233 } 1608 }
1234 1609
1235 if (assoc_req->channel != priv->curbssparams.channel) { 1610 if (assoc_req->channel != priv->channel) {
1236 lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n", 1611 lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
1237 assoc_req->channel); 1612 assoc_req->channel);
1238 goto restore_mesh; 1613 goto restore_mesh;
1239 } 1614 }
1240 1615
1241 if ( assoc_req->secinfo.wep_enabled 1616 if (assoc_req->secinfo.wep_enabled &&
1242 && (assoc_req->wep_keys[0].len 1617 (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
1243 || assoc_req->wep_keys[1].len 1618 assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) {
1244 || assoc_req->wep_keys[2].len
1245 || assoc_req->wep_keys[3].len)) {
1246 /* Make sure WEP keys are re-sent to firmware */ 1619 /* Make sure WEP keys are re-sent to firmware */
1247 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); 1620 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1248 } 1621 }
@@ -1253,7 +1626,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
1253 restore_mesh: 1626 restore_mesh:
1254 if (priv->mesh_dev) 1627 if (priv->mesh_dev)
1255 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1628 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
1256 priv->curbssparams.channel); 1629 priv->channel);
1257 1630
1258 done: 1631 done:
1259 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); 1632 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -1475,7 +1848,7 @@ static int should_stop_adhoc(struct lbs_private *priv,
1475 } 1848 }
1476 1849
1477 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { 1850 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
1478 if (assoc_req->channel != priv->curbssparams.channel) 1851 if (assoc_req->channel != priv->channel)
1479 return 1; 1852 return 1;
1480 } 1853 }
1481 1854
@@ -1557,7 +1930,7 @@ static int lbs_find_best_network_ssid(struct lbs_private *priv,
1557 1930
1558 found = lbs_find_best_ssid_in_list(priv, preferred_mode); 1931 found = lbs_find_best_ssid_in_list(priv, preferred_mode);
1559 if (found && (found->ssid_len > 0)) { 1932 if (found && (found->ssid_len > 0)) {
1560 memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); 1933 memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN);
1561 *out_ssid_len = found->ssid_len; 1934 *out_ssid_len = found->ssid_len;
1562 *out_mode = found->mode; 1935 *out_mode = found->mode;
1563 ret = 0; 1936 ret = 0;
@@ -1609,14 +1982,14 @@ void lbs_association_worker(struct work_struct *work)
1609 assoc_req->secinfo.auth_mode); 1982 assoc_req->secinfo.auth_mode);
1610 1983
1611 /* If 'any' SSID was specified, find an SSID to associate with */ 1984 /* If 'any' SSID was specified, find an SSID to associate with */
1612 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) 1985 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) &&
1613 && !assoc_req->ssid_len) 1986 !assoc_req->ssid_len)
1614 find_any_ssid = 1; 1987 find_any_ssid = 1;
1615 1988
1616 /* But don't use 'any' SSID if there's a valid locked BSSID to use */ 1989 /* But don't use 'any' SSID if there's a valid locked BSSID to use */
1617 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { 1990 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
1618 if (compare_ether_addr(assoc_req->bssid, bssid_any) 1991 if (compare_ether_addr(assoc_req->bssid, bssid_any) &&
1619 && compare_ether_addr(assoc_req->bssid, bssid_off)) 1992 compare_ether_addr(assoc_req->bssid, bssid_off))
1620 find_any_ssid = 0; 1993 find_any_ssid = 0;
1621 } 1994 }
1622 1995
@@ -1678,13 +2051,6 @@ void lbs_association_worker(struct work_struct *work)
1678 goto out; 2051 goto out;
1679 } 2052 }
1680 2053
1681 if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
1682 || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
1683 ret = assoc_helper_wep_keys(priv, assoc_req);
1684 if (ret)
1685 goto out;
1686 }
1687
1688 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { 2054 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
1689 ret = assoc_helper_secinfo(priv, assoc_req); 2055 ret = assoc_helper_secinfo(priv, assoc_req);
1690 if (ret) 2056 if (ret)
@@ -1697,18 +2063,31 @@ void lbs_association_worker(struct work_struct *work)
1697 goto out; 2063 goto out;
1698 } 2064 }
1699 2065
1700 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) 2066 /*
1701 || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { 2067 * v10 FW wants WPA keys to be set/cleared before WEP key operations,
2068 * otherwise it will fail to correctly associate to WEP networks.
2069 * Other firmware versions don't appear to care.
2070 */
2071 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) ||
2072 test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
1702 ret = assoc_helper_wpa_keys(priv, assoc_req); 2073 ret = assoc_helper_wpa_keys(priv, assoc_req);
1703 if (ret) 2074 if (ret)
1704 goto out; 2075 goto out;
1705 } 2076 }
1706 2077
2078 if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) ||
2079 test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
2080 ret = assoc_helper_wep_keys(priv, assoc_req);
2081 if (ret)
2082 goto out;
2083 }
2084
2085
1707 /* SSID/BSSID should be the _last_ config option set, because they 2086 /* SSID/BSSID should be the _last_ config option set, because they
1708 * trigger the association attempt. 2087 * trigger the association attempt.
1709 */ 2088 */
1710 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) 2089 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) ||
1711 || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { 2090 test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
1712 int success = 1; 2091 int success = 1;
1713 2092
1714 ret = assoc_helper_associate(priv, assoc_req); 2093 ret = assoc_helper_associate(priv, assoc_req);
@@ -1775,12 +2154,12 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
1775 assoc_req = priv->pending_assoc_req; 2154 assoc_req = priv->pending_assoc_req;
1776 if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { 2155 if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
1777 memcpy(&assoc_req->ssid, &priv->curbssparams.ssid, 2156 memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
1778 IW_ESSID_MAX_SIZE); 2157 IEEE80211_MAX_SSID_LEN);
1779 assoc_req->ssid_len = priv->curbssparams.ssid_len; 2158 assoc_req->ssid_len = priv->curbssparams.ssid_len;
1780 } 2159 }
1781 2160
1782 if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) 2161 if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
1783 assoc_req->channel = priv->curbssparams.channel; 2162 assoc_req->channel = priv->channel;
1784 2163
1785 if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags)) 2164 if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
1786 assoc_req->band = priv->curbssparams.band; 2165 assoc_req->band = priv->curbssparams.band;