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

brcmfmac: enable 802.11d support in firmware

When the driver gets beacon info containing a country IE from user-space
upon .start_ap() callback, it will enable regulatory 802.11d support.
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarHante Meuleman <meuleman@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 6b89dcb3
...@@ -3966,6 +3966,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, ...@@ -3966,6 +3966,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_if *ifp = netdev_priv(ndev);
const struct brcmf_tlv *ssid_ie; const struct brcmf_tlv *ssid_ie;
const struct brcmf_tlv *country_ie;
struct brcmf_ssid_le ssid_le; struct brcmf_ssid_le ssid_le;
s32 err = -EPERM; s32 err = -EPERM;
const struct brcmf_tlv *rsn_ie; const struct brcmf_tlv *rsn_ie;
...@@ -3975,6 +3976,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, ...@@ -3975,6 +3976,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_fil_bss_enable_le bss_enable; struct brcmf_fil_bss_enable_le bss_enable;
u16 chanspec; u16 chanspec;
bool mbss; bool mbss;
int is_11d;
brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n", brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
settings->chandef.chan->hw_value, settings->chandef.chan->hw_value,
...@@ -3986,6 +3988,13 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, ...@@ -3986,6 +3988,13 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
dev_role = ifp->vif->wdev.iftype; dev_role = ifp->vif->wdev.iftype;
mbss = ifp->vif->mbss; mbss = ifp->vif->mbss;
/* store current 11d setting */
brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_REGULATORY, &ifp->vif->is_11d);
country_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
settings->beacon.tail_len,
WLAN_EID_COUNTRY);
is_11d = country_ie ? 1 : 0;
memset(&ssid_le, 0, sizeof(ssid_le)); memset(&ssid_le, 0, sizeof(ssid_le));
if (settings->ssid == NULL || settings->ssid_len == 0) { if (settings->ssid == NULL || settings->ssid_len == 0) {
ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
...@@ -4051,6 +4060,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, ...@@ -4051,6 +4060,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
goto exit; goto exit;
} }
if (is_11d != ifp->vif->is_11d) {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
is_11d);
if (err < 0) {
brcmf_err("Regulatory Set Error, %d\n", err);
goto exit;
}
}
if (settings->beacon_interval) { if (settings->beacon_interval) {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
settings->beacon_interval); settings->beacon_interval);
...@@ -4083,6 +4100,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, ...@@ -4083,6 +4100,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
brcmf_err("SET INFRA error %d\n", err); brcmf_err("SET INFRA error %d\n", err);
goto exit; goto exit;
} }
} else if (WARN_ON(is_11d != ifp->vif->is_11d)) {
/* Multiple-BSS should use same 11d configuration */
err = -EINVAL;
goto exit;
} }
if (dev_role == NL80211_IFTYPE_AP) { if (dev_role == NL80211_IFTYPE_AP) {
if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss)) if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss))
...@@ -4178,6 +4199,11 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) ...@@ -4178,6 +4199,11 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
brcmf_err("setting INFRA mode failed %d\n", err); brcmf_err("setting INFRA mode failed %d\n", err);
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))
brcmf_fil_iovar_int_set(ifp, "mbss", 0); brcmf_fil_iovar_int_set(ifp, "mbss", 0);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
ifp->vif->is_11d);
if (err < 0)
brcmf_err("restoring REGULATORY setting failed %d\n",
err);
/* Bring device back up so it can be used again */ /* Bring device back up so it can be used again */
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
if (err < 0) if (err < 0)
......
...@@ -200,6 +200,7 @@ struct brcmf_cfg80211_vif { ...@@ -200,6 +200,7 @@ struct brcmf_cfg80211_vif {
struct list_head list; struct list_head list;
u16 mgmt_rx_reg; u16 mgmt_rx_reg;
bool mbss; bool mbss;
int is_11d;
}; };
/* association inform */ /* association inform */
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#define BRCMF_C_SET_RADIO 38 #define BRCMF_C_SET_RADIO 38
#define BRCMF_C_GET_PHYTYPE 39 #define BRCMF_C_GET_PHYTYPE 39
#define BRCMF_C_SET_KEY 45 #define BRCMF_C_SET_KEY 45
#define BRCMF_C_GET_REGULATORY 46
#define BRCMF_C_SET_REGULATORY 47
#define BRCMF_C_SET_PASSIVE_SCAN 49 #define BRCMF_C_SET_PASSIVE_SCAN 49
#define BRCMF_C_SCAN 50 #define BRCMF_C_SCAN 50
#define BRCMF_C_SCAN_RESULTS 51 #define BRCMF_C_SCAN_RESULTS 51
......
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