aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c95
1 files changed, 54 insertions, 41 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ae31968d42d3..f7552c2b74eb 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -478,27 +478,6 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
478 478
479/* frame sending functions */ 479/* frame sending functions */
480 480
481static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
482 struct ieee80211_supported_band *sband,
483 u32 *rates)
484{
485 int i, j, count;
486 *rates = 0;
487 count = 0;
488 for (i = 0; i < supp_rates_len; i++) {
489 int rate = (supp_rates[i] & 0x7F) * 5;
490
491 for (j = 0; j < sband->n_bitrates; j++)
492 if (sband->bitrates[j].bitrate == rate) {
493 *rates |= BIT(j);
494 count++;
495 break;
496 }
497 }
498
499 return count;
500}
501
502static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, 481static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
503 struct sk_buff *skb, u8 ap_ht_param, 482 struct sk_buff *skb, u8 ap_ht_param,
504 struct ieee80211_supported_band *sband, 483 struct ieee80211_supported_band *sband,
@@ -617,12 +596,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
617 struct ieee80211_mgmt *mgmt; 596 struct ieee80211_mgmt *mgmt;
618 u8 *pos, qos_info; 597 u8 *pos, qos_info;
619 size_t offset = 0, noffset; 598 size_t offset = 0, noffset;
620 int i, count, rates_len, supp_rates_len; 599 int i, count, rates_len, supp_rates_len, shift;
621 u16 capab; 600 u16 capab;
622 struct ieee80211_supported_band *sband; 601 struct ieee80211_supported_band *sband;
623 struct ieee80211_chanctx_conf *chanctx_conf; 602 struct ieee80211_chanctx_conf *chanctx_conf;
624 struct ieee80211_channel *chan; 603 struct ieee80211_channel *chan;
625 u32 rates = 0; 604 u32 rate_flags, rates = 0;
626 605
627 sdata_assert_lock(sdata); 606 sdata_assert_lock(sdata);
628 607
@@ -633,8 +612,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
633 return; 612 return;
634 } 613 }
635 chan = chanctx_conf->def.chan; 614 chan = chanctx_conf->def.chan;
615 rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
636 rcu_read_unlock(); 616 rcu_read_unlock();
637 sband = local->hw.wiphy->bands[chan->band]; 617 sband = local->hw.wiphy->bands[chan->band];
618 shift = ieee80211_vif_get_shift(&sdata->vif);
638 619
639 if (assoc_data->supp_rates_len) { 620 if (assoc_data->supp_rates_len) {
640 /* 621 /*
@@ -643,17 +624,24 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
643 * in the association request (e.g. D-Link DAP 1353 in 624 * in the association request (e.g. D-Link DAP 1353 in
644 * b-only mode)... 625 * b-only mode)...
645 */ 626 */
646 rates_len = ieee80211_compatible_rates(assoc_data->supp_rates, 627 rates_len = ieee80211_parse_bitrates(&chanctx_conf->def, sband,
647 assoc_data->supp_rates_len, 628 assoc_data->supp_rates,
648 sband, &rates); 629 assoc_data->supp_rates_len,
630 &rates);
649 } else { 631 } else {
650 /* 632 /*
651 * In case AP not provide any supported rates information 633 * In case AP not provide any supported rates information
652 * before association, we send information element(s) with 634 * before association, we send information element(s) with
653 * all rates that we support. 635 * all rates that we support.
654 */ 636 */
655 rates = ~0; 637 rates_len = 0;
656 rates_len = sband->n_bitrates; 638 for (i = 0; i < sband->n_bitrates; i++) {
639 if ((rate_flags & sband->bitrates[i].flags)
640 != rate_flags)
641 continue;
642 rates |= BIT(i);
643 rates_len++;
644 }
657 } 645 }
658 646
659 skb = alloc_skb(local->hw.extra_tx_headroom + 647 skb = alloc_skb(local->hw.extra_tx_headroom +
@@ -730,8 +718,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
730 count = 0; 718 count = 0;
731 for (i = 0; i < sband->n_bitrates; i++) { 719 for (i = 0; i < sband->n_bitrates; i++) {
732 if (BIT(i) & rates) { 720 if (BIT(i) & rates) {
733 int rate = sband->bitrates[i].bitrate; 721 int rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
734 *pos++ = (u8) (rate / 5); 722 5 * (1 << shift));
723 *pos++ = (u8) rate;
735 if (++count == 8) 724 if (++count == 8)
736 break; 725 break;
737 } 726 }
@@ -744,8 +733,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
744 733
745 for (i++; i < sband->n_bitrates; i++) { 734 for (i++; i < sband->n_bitrates; i++) {
746 if (BIT(i) & rates) { 735 if (BIT(i) & rates) {
747 int rate = sband->bitrates[i].bitrate; 736 int rate;
748 *pos++ = (u8) (rate / 5); 737 rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
738 5 * (1 << shift));
739 *pos++ = (u8) rate;
749 } 740 }
750 } 741 }
751 } 742 }
@@ -2432,15 +2423,16 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
2432 u8 *supp_rates, unsigned int supp_rates_len, 2423 u8 *supp_rates, unsigned int supp_rates_len,
2433 u32 *rates, u32 *basic_rates, 2424 u32 *rates, u32 *basic_rates,
2434 bool *have_higher_than_11mbit, 2425 bool *have_higher_than_11mbit,
2435 int *min_rate, int *min_rate_index) 2426 int *min_rate, int *min_rate_index,
2427 int shift, u32 rate_flags)
2436{ 2428{
2437 int i, j; 2429 int i, j;
2438 2430
2439 for (i = 0; i < supp_rates_len; i++) { 2431 for (i = 0; i < supp_rates_len; i++) {
2440 int rate = (supp_rates[i] & 0x7f) * 5; 2432 int rate = supp_rates[i] & 0x7f;
2441 bool is_basic = !!(supp_rates[i] & 0x80); 2433 bool is_basic = !!(supp_rates[i] & 0x80);
2442 2434
2443 if (rate > 110) 2435 if ((rate * 5 * (1 << shift)) > 110)
2444 *have_higher_than_11mbit = true; 2436 *have_higher_than_11mbit = true;
2445 2437
2446 /* 2438 /*
@@ -2456,12 +2448,20 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
2456 continue; 2448 continue;
2457 2449
2458 for (j = 0; j < sband->n_bitrates; j++) { 2450 for (j = 0; j < sband->n_bitrates; j++) {
2459 if (sband->bitrates[j].bitrate == rate) { 2451 struct ieee80211_rate *br;
2452 int brate;
2453
2454 br = &sband->bitrates[j];
2455 if ((rate_flags & br->flags) != rate_flags)
2456 continue;
2457
2458 brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5);
2459 if (brate == rate) {
2460 *rates |= BIT(j); 2460 *rates |= BIT(j);
2461 if (is_basic) 2461 if (is_basic)
2462 *basic_rates |= BIT(j); 2462 *basic_rates |= BIT(j);
2463 if (rate < *min_rate) { 2463 if ((rate * 5) < *min_rate) {
2464 *min_rate = rate; 2464 *min_rate = rate * 5;
2465 *min_rate_index = j; 2465 *min_rate_index = j;
2466 } 2466 }
2467 break; 2467 break;
@@ -3884,27 +3884,40 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3884 if (!new_sta) 3884 if (!new_sta)
3885 return -ENOMEM; 3885 return -ENOMEM;
3886 } 3886 }
3887
3888 if (new_sta) { 3887 if (new_sta) {
3889 u32 rates = 0, basic_rates = 0; 3888 u32 rates = 0, basic_rates = 0;
3890 bool have_higher_than_11mbit; 3889 bool have_higher_than_11mbit;
3891 int min_rate = INT_MAX, min_rate_index = -1; 3890 int min_rate = INT_MAX, min_rate_index = -1;
3891 struct ieee80211_chanctx_conf *chanctx_conf;
3892 struct ieee80211_supported_band *sband; 3892 struct ieee80211_supported_band *sband;
3893 const struct cfg80211_bss_ies *ies; 3893 const struct cfg80211_bss_ies *ies;
3894 int shift;
3895 u32 rate_flags;
3894 3896
3895 sband = local->hw.wiphy->bands[cbss->channel->band]; 3897 sband = local->hw.wiphy->bands[cbss->channel->band];
3896 3898
3897 err = ieee80211_prep_channel(sdata, cbss); 3899 err = ieee80211_prep_channel(sdata, cbss);
3898 if (err) { 3900 if (err) {
3899 sta_info_free(local, new_sta); 3901 sta_info_free(local, new_sta);
3900 return err; 3902 return -EINVAL;
3901 } 3903 }
3904 shift = ieee80211_vif_get_shift(&sdata->vif);
3905
3906 rcu_read_lock();
3907 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
3908 if (WARN_ON(!chanctx_conf)) {
3909 rcu_read_unlock();
3910 return -EINVAL;
3911 }
3912 rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
3913 rcu_read_unlock();
3902 3914
3903 ieee80211_get_rates(sband, bss->supp_rates, 3915 ieee80211_get_rates(sband, bss->supp_rates,
3904 bss->supp_rates_len, 3916 bss->supp_rates_len,
3905 &rates, &basic_rates, 3917 &rates, &basic_rates,
3906 &have_higher_than_11mbit, 3918 &have_higher_than_11mbit,
3907 &min_rate, &min_rate_index); 3919 &min_rate, &min_rate_index,
3920 shift, rate_flags);
3908 3921
3909 /* 3922 /*
3910 * This used to be a workaround for basic rates missing 3923 * This used to be a workaround for basic rates missing