brcmfmac: add support for nl80211 BSS_SELECT feature
authorArend van Spriel <arend@broadcom.com>
Sun, 17 Apr 2016 14:44:58 +0000 (16:44 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 26 Apr 2016 09:14:27 +0000 (12:14 +0300)
Announce support for nl80211 feature BSS_SELECT and process
BSS selection behaviour provided in .connect() callback.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Lei Zhang <leizh@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h

index 8daad782b3c30d22147fd2c0f0478ec81ad71343..d0631b6cfd5302ee7d73c25937f29f8184e0be83 100644 (file)
@@ -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)
 {
@@ -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);
@@ -6280,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;
index 9e909e3c2f0c0fdae44398ce967c1de015b5bfe6..3e15d64c64813513bc22202dd9e468588699abb0 100644 (file)
@@ -38,7 +38,7 @@ const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME        40
 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME        40
 
-/* boost value for RSSI_DELTA in preferred join selection */
+/* default boost value for RSSI_DELTA in preferred join selection */
 #define BRCMF_JOIN_PREF_RSSI_BOOST     8
 
 #define BRCMF_DEFAULT_TXGLOM_SIZE      32  /* max tx frames in glom chain */
@@ -83,11 +83,31 @@ MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
 static struct brcmfmac_platform_data *brcmfmac_pdata;
 struct brcmf_mp_global_t brcmf_mp_global;
 
+void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
+{
+       struct brcmf_join_pref_params join_pref_params[2];
+       int err;
+
+       /* Setup join_pref to select target by RSSI (boost on 5GHz) */
+       join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
+       join_pref_params[0].len = 2;
+       join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
+       join_pref_params[0].band = WLC_BAND_5G;
+
+       join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
+       join_pref_params[1].len = 2;
+       join_pref_params[1].rssi_gain = 0;
+       join_pref_params[1].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);
+}
+
 int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 {
        s8 eventmask[BRCMF_EVENTING_MASK_LEN];
        u8 buf[BRCMF_DCMD_SMLEN];
-       struct brcmf_join_pref_params join_pref_params[2];
        struct brcmf_rev_info_le revinfo;
        struct brcmf_rev_info *ri;
        char *ptr;
@@ -154,19 +174,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
                goto done;
        }
 
-       /* Setup join_pref to select target by RSSI(with boost on 5GHz) */
-       join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
-       join_pref_params[0].len = 2;
-       join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
-       join_pref_params[0].band = WLC_BAND_5G;
-       join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
-       join_pref_params[1].len = 2;
-       join_pref_params[1].rssi_gain = 0;
-       join_pref_params[1].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);
+       brcmf_c_set_joinpref_default(ifp);
 
        /* Setup event_msgs, enable E_IF */
        err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
index 241ee8d13e54dccbde3bd676a56802bdb229b6bd..647d3cc2a4dca297881e33ae8561641dbeb51705 100644 (file)
@@ -223,6 +223,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
 void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
 void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
 void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
+void brcmf_c_set_joinpref_default(struct brcmf_if *ifp);
 int __init brcmf_core_init(void);
 void __exit brcmf_core_exit(void);
 
index 6b72df17744e5d73b820c78b431cc0bbc5063737..3a9a76dd922265425802b1e7a49c5d33878c496c 100644 (file)
@@ -78,6 +78,7 @@
 #define BRCMF_C_SET_SCAN_CHANNEL_TIME          185
 #define BRCMF_C_SET_SCAN_UNASSOC_TIME          187
 #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON  201
+#define BRCMF_C_SET_ASSOC_PREFER               205
 #define BRCMF_C_GET_VALID_CHANNELS             217
 #define BRCMF_C_GET_KEY_PRIMARY                        235
 #define BRCMF_C_SET_KEY_PRIMARY                        236