Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
[cascardo/linux.git] / drivers / net / wireless / broadcom / brcm80211 / brcmfmac / cfg80211.c
index d5c2a27..d0631b6 100644 (file)
@@ -144,7 +144,7 @@ static struct ieee80211_rate __wl_rates[] = {
 #define wl_a_rates_size                (wl_g_rates_size - 4)
 
 #define CHAN2G(_channel, _freq) {                              \
-       .band                   = IEEE80211_BAND_2GHZ,          \
+       .band                   = NL80211_BAND_2GHZ,            \
        .center_freq            = (_freq),                      \
        .hw_value               = (_channel),                   \
        .flags                  = IEEE80211_CHAN_DISABLED,      \
@@ -153,7 +153,7 @@ static struct ieee80211_rate __wl_rates[] = {
 }
 
 #define CHAN5G(_channel) {                                     \
-       .band                   = IEEE80211_BAND_5GHZ,          \
+       .band                   = NL80211_BAND_5GHZ,            \
        .center_freq            = 5000 + (5 * (_channel)),      \
        .hw_value               = (_channel),                   \
        .flags                  = IEEE80211_CHAN_DISABLED,      \
@@ -181,13 +181,13 @@ static struct ieee80211_channel __wl_5ghz_channels[] = {
  * above is added to the band during setup.
  */
 static const struct ieee80211_supported_band __wl_band_2ghz = {
-       .band = IEEE80211_BAND_2GHZ,
+       .band = NL80211_BAND_2GHZ,
        .bitrates = wl_g_rates,
        .n_bitrates = wl_g_rates_size,
 };
 
 static const struct ieee80211_supported_band __wl_band_5ghz = {
-       .band = IEEE80211_BAND_5GHZ,
+       .band = NL80211_BAND_5GHZ,
        .bitrates = wl_a_rates,
        .n_bitrates = wl_a_rates_size,
 };
@@ -250,6 +250,20 @@ struct parsed_vndr_ies {
        struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
 };
 
+static u8 nl80211_band_to_fwil(enum nl80211_band band)
+{
+       switch (band) {
+       case NL80211_BAND_2GHZ:
+               return WLC_BAND_2G;
+       case NL80211_BAND_5GHZ:
+               return WLC_BAND_5G;
+       default:
+               WARN_ON(1);
+               break;
+       }
+       return 0;
+}
+
 static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
                               struct cfg80211_chan_def *ch)
 {
@@ -292,13 +306,13 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
                WARN_ON_ONCE(1);
        }
        switch (ch->chan->band) {
-       case IEEE80211_BAND_2GHZ:
+       case NL80211_BAND_2GHZ:
                ch_inf.band = BRCMU_CHAN_BAND_2G;
                break;
-       case IEEE80211_BAND_5GHZ:
+       case NL80211_BAND_5GHZ:
                ch_inf.band = BRCMU_CHAN_BAND_5G;
                break;
-       case IEEE80211_BAND_60GHZ:
+       case NL80211_BAND_60GHZ:
        default:
                WARN_ON_ONCE(1);
        }
@@ -1796,6 +1810,50 @@ enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,
        return type;
 }
 
+static void brcmf_set_join_pref(struct brcmf_if *ifp,
+                               struct cfg80211_bss_selection *bss_select)
+{
+       struct brcmf_join_pref_params join_pref_params[2];
+       enum nl80211_band band;
+       int err, i = 0;
+
+       join_pref_params[i].len = 2;
+       join_pref_params[i].rssi_gain = 0;
+
+       if (bss_select->behaviour != NL80211_BSS_SELECT_ATTR_BAND_PREF)
+               brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_ASSOC_PREFER, WLC_BAND_AUTO);
+
+       switch (bss_select->behaviour) {
+       case __NL80211_BSS_SELECT_ATTR_INVALID:
+               brcmf_c_set_joinpref_default(ifp);
+               return;
+       case NL80211_BSS_SELECT_ATTR_BAND_PREF:
+               join_pref_params[i].type = BRCMF_JOIN_PREF_BAND;
+               band = bss_select->param.band_pref;
+               join_pref_params[i].band = nl80211_band_to_fwil(band);
+               i++;
+               break;
+       case NL80211_BSS_SELECT_ATTR_RSSI_ADJUST:
+               join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI_DELTA;
+               band = bss_select->param.adjust.band;
+               join_pref_params[i].band = nl80211_band_to_fwil(band);
+               join_pref_params[i].rssi_gain = bss_select->param.adjust.delta;
+               i++;
+               break;
+       case NL80211_BSS_SELECT_ATTR_RSSI:
+       default:
+               break;
+       }
+       join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI;
+       join_pref_params[i].len = 2;
+       join_pref_params[i].rssi_gain = 0;
+       join_pref_params[i].band = 0;
+       err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
+                                      sizeof(join_pref_params));
+       if (err)
+               brcmf_err("Set join_pref error (%d)\n", err);
+}
+
 static s32
 brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
                       struct cfg80211_connect_params *sme)
@@ -1952,6 +2010,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
                ext_join_params->scan_le.nprobes = cpu_to_le32(-1);
        }
 
+       brcmf_set_join_pref(ifp, &sme->bss_select);
+
        err  = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params,
                                         join_params_size);
        kfree(ext_join_params);
@@ -2679,9 +2739,9 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
        channel = bi->ctl_ch;
 
        if (channel <= CH_MAX_2G_CHANNEL)
-               band = wiphy->bands[IEEE80211_BAND_2GHZ];
+               band = wiphy->bands[NL80211_BAND_2GHZ];
        else
-               band = wiphy->bands[IEEE80211_BAND_5GHZ];
+               band = wiphy->bands[NL80211_BAND_5GHZ];
 
        freq = ieee80211_channel_to_frequency(channel, band->band);
        notify_channel = ieee80211_get_channel(wiphy, freq);
@@ -2788,9 +2848,9 @@ static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg,
        cfg->d11inf.decchspec(&ch);
 
        if (ch.band == BRCMU_CHAN_BAND_2G)
-               band = wiphy->bands[IEEE80211_BAND_2GHZ];
+               band = wiphy->bands[NL80211_BAND_2GHZ];
        else
-               band = wiphy->bands[IEEE80211_BAND_5GHZ];
+               band = wiphy->bands[NL80211_BAND_5GHZ];
 
        freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
        cfg->channel = freq;
@@ -3608,7 +3668,8 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg,
        if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
                wowl_config |= BRCMF_WOWL_UNASSOC;
 
-       brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", strlen("clear"));
+       brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear",
+                                sizeof(struct brcmf_wowl_wakeind_le));
        brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
        brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
        brcmf_bus_wowl_config(cfg->pub->bus_if, true);
@@ -5215,9 +5276,9 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        cfg->d11inf.decchspec(&ch);
 
        if (ch.band == BRCMU_CHAN_BAND_2G)
-               band = wiphy->bands[IEEE80211_BAND_2GHZ];
+               band = wiphy->bands[NL80211_BAND_2GHZ];
        else
-               band = wiphy->bands[IEEE80211_BAND_5GHZ];
+               band = wiphy->bands[NL80211_BAND_5GHZ];
 
        freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
        notify_channel = ieee80211_get_channel(wiphy, freq);
@@ -5707,11 +5768,11 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
        }
 
        wiphy = cfg_to_wiphy(cfg);
-       band = wiphy->bands[IEEE80211_BAND_2GHZ];
+       band = wiphy->bands[NL80211_BAND_2GHZ];
        if (band)
                for (i = 0; i < band->n_channels; i++)
                        band->channels[i].flags = IEEE80211_CHAN_DISABLED;
-       band = wiphy->bands[IEEE80211_BAND_5GHZ];
+       band = wiphy->bands[NL80211_BAND_5GHZ];
        if (band)
                for (i = 0; i < band->n_channels; i++)
                        band->channels[i].flags = IEEE80211_CHAN_DISABLED;
@@ -5722,9 +5783,9 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
                cfg->d11inf.decchspec(&ch);
 
                if (ch.band == BRCMU_CHAN_BAND_2G) {
-                       band = wiphy->bands[IEEE80211_BAND_2GHZ];
+                       band = wiphy->bands[NL80211_BAND_2GHZ];
                } else if (ch.band == BRCMU_CHAN_BAND_5G) {
-                       band = wiphy->bands[IEEE80211_BAND_5GHZ];
+                       band = wiphy->bands[NL80211_BAND_5GHZ];
                } else {
                        brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
                        continue;
@@ -5839,7 +5900,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
                        return err;
                }
 
-               band = cfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
+               band = cfg_to_wiphy(cfg)->bands[NL80211_BAND_2GHZ];
                list = (struct brcmf_chanspec_list *)pbuf;
                num_chan = le32_to_cpu(list->count);
                for (i = 0; i < num_chan; i++) {
@@ -5871,11 +5932,11 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
        band = WLC_BAND_2G;
        err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band);
        if (!err) {
-               bw_cap[IEEE80211_BAND_2GHZ] = band;
+               bw_cap[NL80211_BAND_2GHZ] = band;
                band = WLC_BAND_5G;
                err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band);
                if (!err) {
-                       bw_cap[IEEE80211_BAND_5GHZ] = band;
+                       bw_cap[NL80211_BAND_5GHZ] = band;
                        return;
                }
                WARN_ON(1);
@@ -5890,14 +5951,14 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
 
        switch (mimo_bwcap) {
        case WLC_N_BW_40ALL:
-               bw_cap[IEEE80211_BAND_2GHZ] |= WLC_BW_40MHZ_BIT;
+               bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_40MHZ_BIT;
                /* fall-thru */
        case WLC_N_BW_20IN2G_40IN5G:
-               bw_cap[IEEE80211_BAND_5GHZ] |= WLC_BW_40MHZ_BIT;
+               bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_40MHZ_BIT;
                /* fall-thru */
        case WLC_N_BW_20ALL:
-               bw_cap[IEEE80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT;
-               bw_cap[IEEE80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT;
+               bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT;
+               bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT;
                break;
        default:
                brcmf_err("invalid mimo_bw_cap value\n");
@@ -5938,7 +5999,7 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
        __le16 mcs_map;
 
        /* not allowed in 2.4G band */
-       if (band->band == IEEE80211_BAND_2GHZ)
+       if (band->band == NL80211_BAND_2GHZ)
                return;
 
        band->vht_cap.vht_supported = true;
@@ -5997,8 +6058,8 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
                brcmf_get_bwcap(ifp, bw_cap);
        }
        brcmf_dbg(INFO, "nmode=%d, vhtmode=%d, bw_cap=(%d, %d)\n",
-                 nmode, vhtmode, bw_cap[IEEE80211_BAND_2GHZ],
-                 bw_cap[IEEE80211_BAND_5GHZ]);
+                 nmode, vhtmode, bw_cap[NL80211_BAND_2GHZ],
+                 bw_cap[NL80211_BAND_5GHZ]);
 
        err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain);
        if (err) {
@@ -6279,6 +6340,10 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
        wiphy->n_cipher_suites = ARRAY_SIZE(brcmf_cipher_suites);
        if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
                wiphy->n_cipher_suites--;
+       wiphy->bss_select_support = BIT(NL80211_BSS_SELECT_ATTR_RSSI) |
+                                   BIT(NL80211_BSS_SELECT_ATTR_BAND_PREF) |
+                                   BIT(NL80211_BSS_SELECT_ATTR_RSSI_ADJUST);
+
        wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
                        WIPHY_FLAG_OFFCHAN_TX |
                        WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
@@ -6321,7 +6386,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
                        }
 
                        band->n_channels = ARRAY_SIZE(__wl_2ghz_channels);
-                       wiphy->bands[IEEE80211_BAND_2GHZ] = band;
+                       wiphy->bands[NL80211_BAND_2GHZ] = band;
                }
                if (bandlist[i] == cpu_to_le32(WLC_BAND_5G)) {
                        band = kmemdup(&__wl_band_5ghz, sizeof(__wl_band_5ghz),
@@ -6338,7 +6403,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
                        }
 
                        band->n_channels = ARRAY_SIZE(__wl_5ghz_channels);
-                       wiphy->bands[IEEE80211_BAND_5GHZ] = band;
+                       wiphy->bands[NL80211_BAND_5GHZ] = band;
                }
        }
        err = brcmf_setup_wiphybands(wiphy);
@@ -6604,13 +6669,13 @@ static void brcmf_free_wiphy(struct wiphy *wiphy)
                        kfree(wiphy->iface_combinations[i].limits);
        }
        kfree(wiphy->iface_combinations);
-       if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
-               kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
-               kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
+       if (wiphy->bands[NL80211_BAND_2GHZ]) {
+               kfree(wiphy->bands[NL80211_BAND_2GHZ]->channels);
+               kfree(wiphy->bands[NL80211_BAND_2GHZ]);
        }
-       if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
-               kfree(wiphy->bands[IEEE80211_BAND_5GHZ]->channels);
-               kfree(wiphy->bands[IEEE80211_BAND_5GHZ]);
+       if (wiphy->bands[NL80211_BAND_5GHZ]) {
+               kfree(wiphy->bands[NL80211_BAND_5GHZ]->channels);
+               kfree(wiphy->bands[NL80211_BAND_5GHZ]);
        }
        wiphy_free(wiphy);
 }
@@ -6698,8 +6763,8 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
         * cfg80211 here that we do and have it decide we can enable
         * it. But first check if device does support 2G operation.
         */
-       if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
-               cap = &wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap;
+       if (wiphy->bands[NL80211_BAND_2GHZ]) {
+               cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap;
                *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
        }
        err = wiphy_register(wiphy);