Commit 7705ba6f authored by Arend van Spriel's avatar Arend van Spriel Committed by Kalle Valo

brcmfmac: add support for nl80211 BSS_SELECT feature

Announce support for nl80211 feature BSS_SELECT and process
BSS selection behaviour provided in .connect() callback.
Reviewed-by: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarLei Zhang <leizh@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 005a425b
...@@ -250,6 +250,20 @@ struct parsed_vndr_ies { ...@@ -250,6 +250,20 @@ struct parsed_vndr_ies {
struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT]; 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, static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
struct cfg80211_chan_def *ch) struct cfg80211_chan_def *ch)
{ {
...@@ -1796,6 +1810,50 @@ enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, ...@@ -1796,6 +1810,50 @@ enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,
return type; 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 static s32
brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_connect_params *sme) struct cfg80211_connect_params *sme)
...@@ -1952,6 +2010,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, ...@@ -1952,6 +2010,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
ext_join_params->scan_le.nprobes = cpu_to_le32(-1); 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, err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params,
join_params_size); join_params_size);
kfree(ext_join_params); kfree(ext_join_params);
...@@ -6280,6 +6340,10 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) ...@@ -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); wiphy->n_cipher_suites = ARRAY_SIZE(brcmf_cipher_suites);
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
wiphy->n_cipher_suites--; 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->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_OFFCHAN_TX |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
......
...@@ -38,7 +38,7 @@ const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; ...@@ -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_CHANNEL_TIME 40
#define BRCMF_DEFAULT_SCAN_UNASSOC_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_JOIN_PREF_RSSI_BOOST 8
#define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ #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"); ...@@ -83,11 +83,31 @@ MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
static struct brcmfmac_platform_data *brcmfmac_pdata; static struct brcmfmac_platform_data *brcmfmac_pdata;
struct brcmf_mp_global_t brcmf_mp_global; 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) int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
{ {
s8 eventmask[BRCMF_EVENTING_MASK_LEN]; s8 eventmask[BRCMF_EVENTING_MASK_LEN];
u8 buf[BRCMF_DCMD_SMLEN]; u8 buf[BRCMF_DCMD_SMLEN];
struct brcmf_join_pref_params join_pref_params[2];
struct brcmf_rev_info_le revinfo; struct brcmf_rev_info_le revinfo;
struct brcmf_rev_info *ri; struct brcmf_rev_info *ri;
char *ptr; char *ptr;
...@@ -154,19 +174,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) ...@@ -154,19 +174,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
goto done; goto done;
} }
/* Setup join_pref to select target by RSSI(with boost on 5GHz) */ brcmf_c_set_joinpref_default(ifp);
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);
/* Setup event_msgs, enable E_IF */ /* Setup event_msgs, enable E_IF */
err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
......
...@@ -223,6 +223,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, ...@@ -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_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_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); 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); int __init brcmf_core_init(void);
void __exit brcmf_core_exit(void); void __exit brcmf_core_exit(void);
......
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 #define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 #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_VALID_CHANNELS 217
#define BRCMF_C_GET_KEY_PRIMARY 235 #define BRCMF_C_GET_KEY_PRIMARY 235
#define BRCMF_C_SET_KEY_PRIMARY 236 #define BRCMF_C_SET_KEY_PRIMARY 236
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment