diff options
Diffstat (limited to 'drivers/net/wireless/libertas/join.c')
-rw-r--r-- | drivers/net/wireless/libertas/join.c | 203 |
1 files changed, 105 insertions, 98 deletions
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c index 381739d6ed96..78e398d6f5f3 100644 --- a/drivers/net/wireless/libertas/join.c +++ b/drivers/net/wireless/libertas/join.c | |||
@@ -17,8 +17,12 @@ | |||
17 | #include "dev.h" | 17 | #include "dev.h" |
18 | #include "assoc.h" | 18 | #include "assoc.h" |
19 | 19 | ||
20 | /* Supported rates for ad-hoc B mode */ | ||
21 | u8 adhoc_rates_b[5] = { 0x02, 0x04, 0x0b, 0x16, 0x00 }; | ||
22 | |||
23 | |||
20 | /** | 24 | /** |
21 | * @brief This function finds out the common rates between rate1 and rate2. | 25 | * @brief This function finds common rates between rate1 and card rates. |
22 | * | 26 | * |
23 | * It will fill common rates in rate1 as output if found. | 27 | * It will fill common rates in rate1 as output if found. |
24 | * | 28 | * |
@@ -27,61 +31,87 @@ | |||
27 | * | 31 | * |
28 | * @param adapter A pointer to wlan_adapter structure | 32 | * @param adapter A pointer to wlan_adapter structure |
29 | * @param rate1 the buffer which keeps input and output | 33 | * @param rate1 the buffer which keeps input and output |
30 | * @param rate1_size the size of rate1 buffer | 34 | * @param rate1_size the size of rate1 buffer; new size of buffer on return |
31 | * @param rate2 the buffer which keeps rate2 | ||
32 | * @param rate2_size the size of rate2 buffer. | ||
33 | * | 35 | * |
34 | * @return 0 or -1 | 36 | * @return 0 or -1 |
35 | */ | 37 | */ |
36 | static int get_common_rates(wlan_adapter * adapter, u8 * rate1, | 38 | static int get_common_rates(wlan_adapter * adapter, u8 * rates, u16 *rates_size) |
37 | int rate1_size, u8 * rate2, int rate2_size) | ||
38 | { | 39 | { |
39 | u8 *ptr = rate1; | 40 | u8 *card_rates = libertas_bg_rates; |
40 | int ret = 0; | 41 | size_t num_card_rates = sizeof(libertas_bg_rates); |
42 | int ret = 0, i, j; | ||
41 | u8 tmp[30]; | 43 | u8 tmp[30]; |
42 | int i; | 44 | size_t tmp_size = 0; |
43 | 45 | ||
44 | memset(&tmp, 0, sizeof(tmp)); | 46 | /* For each rate in card_rates that exists in rate1, copy to tmp */ |
45 | memcpy(&tmp, rate1, min_t(size_t, rate1_size, sizeof(tmp))); | 47 | for (i = 0; card_rates[i] && (i < num_card_rates); i++) { |
46 | memset(rate1, 0, rate1_size); | 48 | for (j = 0; rates[j] && (j < *rates_size); j++) { |
47 | 49 | if (rates[j] == card_rates[i]) | |
48 | /* Mask the top bit of the original values */ | 50 | tmp[tmp_size++] = card_rates[i]; |
49 | for (i = 0; tmp[i] && i < sizeof(tmp); i++) | ||
50 | tmp[i] &= 0x7F; | ||
51 | |||
52 | for (i = 0; rate2[i] && i < rate2_size; i++) { | ||
53 | /* Check for Card Rate in tmp, excluding the top bit */ | ||
54 | if (strchr(tmp, rate2[i] & 0x7F)) { | ||
55 | /* values match, so copy the Card Rate to rate1 */ | ||
56 | *rate1++ = rate2[i]; | ||
57 | } | 51 | } |
58 | } | 52 | } |
59 | 53 | ||
60 | lbs_dbg_hex("rate1 (AP) rates:", tmp, sizeof(tmp)); | 54 | lbs_dbg_hex("rate1 (AP) rates:", rates, *rates_size); |
61 | lbs_dbg_hex("rate2 (Card) rates:", rate2, rate2_size); | 55 | lbs_dbg_hex("rate2 (Card) rates:", card_rates, num_card_rates); |
62 | lbs_dbg_hex("Common rates:", ptr, rate1_size); | 56 | lbs_dbg_hex("Common rates:", tmp, tmp_size); |
63 | lbs_deb_join("Tx datarate is set to 0x%X\n", adapter->datarate); | 57 | lbs_deb_join("Tx datarate is currently 0x%X\n", adapter->cur_rate); |
64 | 58 | ||
65 | if (!adapter->is_datarate_auto) { | 59 | if (!adapter->auto_rate) { |
66 | while (*ptr) { | 60 | for (i = 0; i < tmp_size; i++) { |
67 | if ((*ptr & 0x7f) == adapter->datarate) { | 61 | if (tmp[i] == adapter->cur_rate) |
68 | ret = 0; | ||
69 | goto done; | 62 | goto done; |
70 | } | ||
71 | ptr++; | ||
72 | } | 63 | } |
73 | lbs_pr_alert( "Previously set fixed data rate %#x isn't " | 64 | lbs_pr_alert("Previously set fixed data rate %#x isn't " |
74 | "compatible with the network.\n", adapter->datarate); | 65 | "compatible with the network.\n", adapter->cur_rate); |
75 | |||
76 | ret = -1; | 66 | ret = -1; |
77 | goto done; | 67 | goto done; |
78 | } | 68 | } |
79 | |||
80 | ret = 0; | 69 | ret = 0; |
70 | |||
81 | done: | 71 | done: |
72 | memset(rates, 0, *rates_size); | ||
73 | *rates_size = min_t(int, tmp_size, *rates_size); | ||
74 | memcpy(rates, tmp, *rates_size); | ||
82 | return ret; | 75 | return ret; |
83 | } | 76 | } |
84 | 77 | ||
78 | |||
79 | /** | ||
80 | * @brief Sets the MSB on basic rates as the firmware requires | ||
81 | * | ||
82 | * Scan through an array and set the MSB for basic data rates. | ||
83 | * | ||
84 | * @param rates buffer of data rates | ||
85 | * @param len size of buffer | ||
86 | */ | ||
87 | static void libertas_set_basic_rate_flags(u8 * rates, size_t len) | ||
88 | { | ||
89 | int i; | ||
90 | |||
91 | for (i = 0; i < len; i++) { | ||
92 | if (rates[i] == 0x02 || rates[i] == 0x04 || | ||
93 | rates[i] == 0x0b || rates[i] == 0x16) | ||
94 | rates[i] |= 0x80; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * @brief Unsets the MSB on basic rates | ||
100 | * | ||
101 | * Scan through an array and unset the MSB for basic data rates. | ||
102 | * | ||
103 | * @param rates buffer of data rates | ||
104 | * @param len size of buffer | ||
105 | */ | ||
106 | void libertas_unset_basic_rate_flags(u8 * rates, size_t len) | ||
107 | { | ||
108 | int i; | ||
109 | |||
110 | for (i = 0; i < len; i++) | ||
111 | rates[i] &= 0x7f; | ||
112 | } | ||
113 | |||
114 | |||
85 | int libertas_send_deauth(wlan_private * priv) | 115 | int libertas_send_deauth(wlan_private * priv) |
86 | { | 116 | { |
87 | wlan_adapter *adapter = priv->adapter; | 117 | wlan_adapter *adapter = priv->adapter; |
@@ -330,9 +360,7 @@ int libertas_cmd_80211_associate(wlan_private * priv, | |||
330 | int ret = 0; | 360 | int ret = 0; |
331 | struct assoc_request * assoc_req = pdata_buf; | 361 | struct assoc_request * assoc_req = pdata_buf; |
332 | struct bss_descriptor * bss = &assoc_req->bss; | 362 | struct bss_descriptor * bss = &assoc_req->bss; |
333 | u8 *card_rates; | ||
334 | u8 *pos; | 363 | u8 *pos; |
335 | int card_rates_size; | ||
336 | u16 tmpcap, tmplen; | 364 | u16 tmpcap, tmplen; |
337 | struct mrvlietypes_ssidparamset *ssid; | 365 | struct mrvlietypes_ssidparamset *ssid; |
338 | struct mrvlietypes_phyparamset *phy; | 366 | struct mrvlietypes_phyparamset *phy; |
@@ -386,23 +414,24 @@ int libertas_cmd_80211_associate(wlan_private * priv, | |||
386 | 414 | ||
387 | rates = (struct mrvlietypes_ratesparamset *) pos; | 415 | rates = (struct mrvlietypes_ratesparamset *) pos; |
388 | rates->header.type = cpu_to_le16(TLV_TYPE_RATES); | 416 | rates->header.type = cpu_to_le16(TLV_TYPE_RATES); |
389 | 417 | memcpy(&rates->rates, &bss->rates, MAX_RATES); | |
390 | memcpy(&rates->rates, &bss->libertas_supported_rates, WLAN_SUPPORTED_RATES); | 418 | tmplen = MAX_RATES; |
391 | 419 | if (get_common_rates(adapter, rates->rates, &tmplen)) { | |
392 | card_rates = libertas_supported_rates; | ||
393 | card_rates_size = sizeof(libertas_supported_rates); | ||
394 | |||
395 | if (get_common_rates(adapter, rates->rates, WLAN_SUPPORTED_RATES, | ||
396 | card_rates, card_rates_size)) { | ||
397 | ret = -1; | 420 | ret = -1; |
398 | goto done; | 421 | goto done; |
399 | } | 422 | } |
400 | |||
401 | tmplen = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES); | ||
402 | adapter->curbssparams.numofrates = tmplen; | ||
403 | |||
404 | pos += sizeof(rates->header) + tmplen; | 423 | pos += sizeof(rates->header) + tmplen; |
405 | rates->header.len = cpu_to_le16(tmplen); | 424 | rates->header.len = cpu_to_le16(tmplen); |
425 | lbs_deb_join("ASSOC_CMD: num rates = %u\n", tmplen); | ||
426 | |||
427 | /* Copy the infra. association rates into Current BSS state structure */ | ||
428 | memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates)); | ||
429 | memcpy(&adapter->curbssparams.rates, &rates->rates, tmplen); | ||
430 | |||
431 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
432 | * copying to current bss rates. | ||
433 | */ | ||
434 | libertas_set_basic_rate_flags(rates->rates, tmplen); | ||
406 | 435 | ||
407 | if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { | 436 | if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { |
408 | rsn = (struct mrvlietypes_rsnparamset *) pos; | 437 | rsn = (struct mrvlietypes_rsnparamset *) pos; |
@@ -419,14 +448,6 @@ int libertas_cmd_80211_associate(wlan_private * priv, | |||
419 | /* update curbssparams */ | 448 | /* update curbssparams */ |
420 | adapter->curbssparams.channel = bss->phyparamset.dsparamset.currentchan; | 449 | adapter->curbssparams.channel = bss->phyparamset.dsparamset.currentchan; |
421 | 450 | ||
422 | /* Copy the infra. association rates into Current BSS state structure */ | ||
423 | memcpy(&adapter->curbssparams.datarates, &rates->rates, | ||
424 | min_t(size_t, sizeof(adapter->curbssparams.datarates), | ||
425 | cpu_to_le16(rates->header.len))); | ||
426 | |||
427 | lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n", | ||
428 | cpu_to_le16(rates->header.len)); | ||
429 | |||
430 | if (libertas_parse_dnld_countryinfo_11d(priv, bss)) { | 451 | if (libertas_parse_dnld_countryinfo_11d(priv, bss)) { |
431 | ret = -1; | 452 | ret = -1; |
432 | goto done; | 453 | goto done; |
@@ -454,9 +475,9 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, | |||
454 | struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads; | 475 | struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads; |
455 | int ret = 0; | 476 | int ret = 0; |
456 | int cmdappendsize = 0; | 477 | int cmdappendsize = 0; |
457 | int i; | ||
458 | struct assoc_request * assoc_req = pdata_buf; | 478 | struct assoc_request * assoc_req = pdata_buf; |
459 | u16 tmpcap = 0; | 479 | u16 tmpcap = 0; |
480 | size_t ratesize = 0; | ||
460 | 481 | ||
461 | lbs_deb_enter(LBS_DEB_JOIN); | 482 | lbs_deb_enter(LBS_DEB_JOIN); |
462 | 483 | ||
@@ -526,28 +547,26 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv, | |||
526 | /* probedelay */ | 547 | /* probedelay */ |
527 | adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | 548 | adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); |
528 | 549 | ||
529 | memset(adhs->datarate, 0, sizeof(adhs->datarate)); | 550 | memset(adhs->rates, 0, sizeof(adhs->rates)); |
530 | |||
531 | if (adapter->adhoc_grate_enabled) { | 551 | if (adapter->adhoc_grate_enabled) { |
532 | memcpy(adhs->datarate, libertas_adhoc_rates_g, | 552 | ratesize = min(sizeof(adhs->rates), sizeof(libertas_bg_rates)); |
533 | min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_g))); | 553 | memcpy(adhs->rates, libertas_bg_rates, ratesize); |
534 | } else { | 554 | } else { |
535 | memcpy(adhs->datarate, libertas_adhoc_rates_b, | 555 | ratesize = min(sizeof(adhs->rates), sizeof(adhoc_rates_b)); |
536 | min(sizeof(adhs->datarate), sizeof(libertas_adhoc_rates_b))); | 556 | memcpy(adhs->rates, adhoc_rates_b, ratesize); |
537 | } | 557 | } |
538 | 558 | ||
539 | /* Find the last non zero */ | ||
540 | for (i = 0; i < sizeof(adhs->datarate) && adhs->datarate[i]; i++) ; | ||
541 | |||
542 | adapter->curbssparams.numofrates = i; | ||
543 | |||
544 | /* Copy the ad-hoc creating rates into Current BSS state structure */ | 559 | /* Copy the ad-hoc creating rates into Current BSS state structure */ |
545 | memcpy(&adapter->curbssparams.datarates, | 560 | memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates)); |
546 | &adhs->datarate, adapter->curbssparams.numofrates); | 561 | memcpy(&adapter->curbssparams.rates, &adhs->rates, ratesize); |
562 | |||
563 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
564 | * copying to current bss rates. | ||
565 | */ | ||
566 | libertas_set_basic_rate_flags(adhs->rates, ratesize); | ||
547 | 567 | ||
548 | lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n", | 568 | lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n", |
549 | adhs->datarate[0], adhs->datarate[1], | 569 | adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]); |
550 | adhs->datarate[2], adhs->datarate[3]); | ||
551 | 570 | ||
552 | lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n"); | 571 | lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n"); |
553 | 572 | ||
@@ -584,9 +603,7 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv, | |||
584 | struct bss_descriptor *bss = &assoc_req->bss; | 603 | struct bss_descriptor *bss = &assoc_req->bss; |
585 | int cmdappendsize = 0; | 604 | int cmdappendsize = 0; |
586 | int ret = 0; | 605 | int ret = 0; |
587 | u8 *card_rates; | 606 | u16 ratesize = 0; |
588 | int card_rates_size; | ||
589 | int i; | ||
590 | 607 | ||
591 | lbs_deb_enter(LBS_DEB_JOIN); | 608 | lbs_deb_enter(LBS_DEB_JOIN); |
592 | 609 | ||
@@ -619,36 +636,26 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv, | |||
619 | /* probedelay */ | 636 | /* probedelay */ |
620 | join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | 637 | join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); |
621 | 638 | ||
622 | /* Copy Data rates from the rates recorded in scan response */ | ||
623 | memset(join_cmd->bss.datarates, 0, sizeof(join_cmd->bss.datarates)); | ||
624 | memcpy(join_cmd->bss.datarates, bss->datarates, | ||
625 | min(sizeof(join_cmd->bss.datarates), sizeof(bss->datarates))); | ||
626 | |||
627 | card_rates = libertas_supported_rates; | ||
628 | card_rates_size = sizeof(libertas_supported_rates); | ||
629 | |||
630 | adapter->curbssparams.channel = bss->channel; | 639 | adapter->curbssparams.channel = bss->channel; |
631 | 640 | ||
632 | if (get_common_rates(adapter, join_cmd->bss.datarates, | 641 | /* Copy Data rates from the rates recorded in scan response */ |
633 | sizeof(join_cmd->bss.datarates), | 642 | memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates)); |
634 | card_rates, card_rates_size)) { | 643 | ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES); |
644 | memcpy(join_cmd->bss.rates, bss->rates, ratesize); | ||
645 | if (get_common_rates(adapter, join_cmd->bss.rates, &ratesize)) { | ||
635 | lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n"); | 646 | lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n"); |
636 | ret = -1; | 647 | ret = -1; |
637 | goto done; | 648 | goto done; |
638 | } | 649 | } |
639 | 650 | ||
640 | /* Find the last non zero */ | 651 | /* Copy the ad-hoc creating rates into Current BSS state structure */ |
641 | for (i = 0; i < sizeof(join_cmd->bss.datarates) | 652 | memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates)); |
642 | && join_cmd->bss.datarates[i]; i++) ; | 653 | memcpy(&adapter->curbssparams.rates, join_cmd->bss.rates, ratesize); |
643 | |||
644 | adapter->curbssparams.numofrates = i; | ||
645 | 654 | ||
646 | /* | 655 | /* Set MSB on basic rates as the firmware requires, but _after_ |
647 | * Copy the adhoc joining rates to Current BSS State structure | 656 | * copying to current bss rates. |
648 | */ | 657 | */ |
649 | memcpy(adapter->curbssparams.datarates, | 658 | libertas_set_basic_rate_flags(join_cmd->bss.rates, ratesize); |
650 | join_cmd->bss.datarates, | ||
651 | adapter->curbssparams.numofrates); | ||
652 | 659 | ||
653 | join_cmd->bss.ssparamset.ibssparamset.atimwindow = | 660 | join_cmd->bss.ssparamset.ibssparamset.atimwindow = |
654 | cpu_to_le16(bss->atimwindow); | 661 | cpu_to_le16(bss->atimwindow); |