123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
- Date: Fri, 27 May 2016 21:07:19 +0200
- Subject: [PATCH] brcmfmac: fix setting AP channel with new firmwares
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- Firmware for new chipsets is based on a new major version of code
- internally maintained at Broadcom. E.g. brcmfmac4366b-pcie.bin (used for
- BCM4366B1) is based on 10.10.69.3309 while brcmfmac43602-pcie.ap.bin was
- based on 7.35.177.56.
- Currently setting AP 5 GHz channel doesn't work reliably with BCM4366B1.
- When setting e.g. 36 control channel with VHT80 (center channel 42)
- firmware may randomly pick one of:
- 1) 52 control channel with 58 as center one
- 2) 100 control channel with 106 as center one
- 3) 116 control channel with 122 as center one
- 4) 149 control channel with 155 as center one
- It seems new firmwares require setting AP mode (BRCMF_C_SET_AP) before
- specifying a channel. Changing an order of firmware calls fixes the
- problem. This requirement resulted in two separated "chanspec" calls,
- one in AP code path and one in P2P path.
- This fix was verified with BCM4366B1 and tested for regressions on
- BCM43602.
- Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
- Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
- ---
- --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
- +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
- @@ -4458,7 +4458,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
- struct brcmf_join_params join_params;
- enum nl80211_iftype dev_role;
- struct brcmf_fil_bss_enable_le bss_enable;
- - u16 chanspec;
- + u16 chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);
- bool mbss;
- int is_11d;
-
- @@ -4534,16 +4534,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
-
- brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
-
- + /* Parameters shared by all radio interfaces */
- if (!mbss) {
- - chanspec = chandef_to_chanspec(&cfg->d11inf,
- - &settings->chandef);
- - err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
- - if (err < 0) {
- - brcmf_err("Set Channel failed: chspec=%d, %d\n",
- - chanspec, err);
- - goto exit;
- - }
- -
- if (is_11d != ifp->vif->is_11d) {
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
- is_11d);
- @@ -4591,6 +4583,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
- err = -EINVAL;
- goto exit;
- }
- +
- + /* Interface specific setup */
- if (dev_role == NL80211_IFTYPE_AP) {
- if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss))
- brcmf_fil_iovar_int_set(ifp, "mbss", 1);
- @@ -4600,6 +4594,17 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
- brcmf_err("setting AP mode failed %d\n", err);
- goto exit;
- }
- + if (!mbss) {
- + /* Firmware 10.x requires setting channel after enabling
- + * AP and before bringing interface up.
- + */
- + err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
- + if (err < 0) {
- + brcmf_err("Set Channel failed: chspec=%d, %d\n",
- + chanspec, err);
- + goto exit;
- + }
- + }
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
- if (err < 0) {
- brcmf_err("BRCMF_C_UP error (%d)\n", err);
- @@ -4621,7 +4626,13 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
- goto exit;
- }
- brcmf_dbg(TRACE, "AP mode configuration complete\n");
- - } else {
- + } else if (dev_role == NL80211_IFTYPE_P2P_GO) {
- + err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
- + if (err < 0) {
- + brcmf_err("Set Channel failed: chspec=%d, %d\n",
- + chanspec, err);
- + goto exit;
- + }
- err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le,
- sizeof(ssid_le));
- if (err < 0) {
- @@ -4638,7 +4649,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
- }
-
- brcmf_dbg(TRACE, "GO mode configuration complete\n");
- + } else {
- + WARN_ON(1);
- }
- +
- set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
- brcmf_net_setcarrier(ifp, true);
-
|