mac80211: brcmfmac: fix support for BCM4366

1) Fix setting AP channel
2) Improve BSS management to avoid:
[ 3602.929199] brcmfmac: brcmf_ap_add_vif: timeout occurred

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>

Backport of r49383

git-svn-id: svn://svn.openwrt.org/openwrt/branches/chaos_calmer@49386 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
Rafał Miłecki 2016-06-17 07:50:22 +00:00 committed by Luka Perkov
parent 0e29de61f7
commit 468fe950b8
3 changed files with 233 additions and 0 deletions

View File

@ -0,0 +1,59 @@
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Date: Fri, 27 May 2016 10:54:28 +0200
Subject: [PATCH] brcmfmac: print errors if creating interface fails
This is helpful for debugging. Without this all I was getting from "iw"
command on failed creating of P2P interface was:
> command failed: Too many open files in system (-23)
Signed-off-by: Rafal Milecki <zajec5@gmail.com>
[arend@broadcom.com: reduce error prints upon iface creation]
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Reviewed-by: Julian Calaby <julian.calaby@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
@@ -649,20 +649,24 @@ static struct wireless_dev *brcmf_cfg802
return ERR_PTR(-EOPNOTSUPP);
case NL80211_IFTYPE_AP:
wdev = brcmf_ap_add_vif(wiphy, name, flags, params);
- if (!IS_ERR(wdev))
- brcmf_cfg80211_update_proto_addr_mode(wdev);
- return wdev;
+ break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
wdev = brcmf_p2p_add_vif(wiphy, name, name_assign_type, type, flags, params);
- if (!IS_ERR(wdev))
- brcmf_cfg80211_update_proto_addr_mode(wdev);
- return wdev;
+ break;
case NL80211_IFTYPE_UNSPECIFIED:
default:
return ERR_PTR(-EINVAL);
}
+
+ if (IS_ERR(wdev))
+ brcmf_err("add iface %s type %d failed: err=%d\n",
+ name, type, (int)PTR_ERR(wdev));
+ else
+ brcmf_cfg80211_update_proto_addr_mode(wdev);
+
+ return wdev;
}
static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -2020,8 +2020,6 @@ static int brcmf_p2p_request_p2p_if(stru
err = brcmf_fil_iovar_data_set(ifp, "p2p_ifadd", &if_request,
sizeof(if_request));
- if (err)
- return err;
return err;
}

View File

@ -0,0 +1,114 @@
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
@@ -4304,7 +4304,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;
@@ -4380,16 +4380,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);
@@ -4437,6 +4429,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);
@@ -4446,6 +4440,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);
@@ -4467,7 +4472,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) {
@@ -4484,7 +4495,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);

View File

@ -0,0 +1,60 @@
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Date: Mon, 30 May 2016 06:40:54 +0200
Subject: [PATCH] brcmfmac: don't remove interface on link down firmware event
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
There are two firmware events we handle similarly in brcmfmac:
BRCMF_E_LINK and BRCMF_E_IF. The difference from firmware point of view
is that the first one means BSS remains present in the firmware. Trying
to (re)create it (e.g. when adding new virtual interface) will result in
an error.
Current code treats both events in a similar way. It removes Linux
interface for each of them. It works OK with e.g. BCM43602. Its firmware
generates both events for each interface. It means we get BRCMF_E_LINK
and remove interface. That is soon followed by BRCMF_E_IF which means
BSS was also removed in a firmware. The only downside of this is a
harmless error like:
[ 208.643180] brcmfmac: brcmf_fweh_call_event_handler: no interface object
Unfortunately BCM4366 firmware doesn't automatically remove BSS and so
it doesn't generate BRCMF_E_IF. In such case we incorrectly remove Linux
interface on BRCMF_E_LINK as BSS is still present in the firmware. It
results in an error when trying to re-create virtual interface, e.g.:
> iw phy phy1 interface add wlan1-1 type __ap
[ 3602.929199] brcmfmac: brcmf_ap_add_vif: timeout occurred
command failed: I/O error (-5)
With this patch we don't remove Linux interface while firmware keeps
BSS. Thanks to this we keep a consistent states of host driver and
device firmware.
Further improvement should be to mark BSS as disabled and remove
interface on BRCMF_E_LINK. Then we should add support for reusing
BSS-es.
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
@@ -5269,7 +5269,6 @@ brcmf_notify_connect_status_ap(struct br
struct net_device *ndev,
const struct brcmf_event_msg *e, void *data)
{
- struct brcmf_if *ifp = netdev_priv(ndev);
static int generation;
u32 event = e->event_code;
u32 reason = e->reason;
@@ -5280,8 +5279,6 @@ brcmf_notify_connect_status_ap(struct br
ndev != cfg_to_ndev(cfg)) {
brcmf_dbg(CONN, "AP mode link down\n");
complete(&cfg->vif_disabled);
- if (ifp->vif->mbss)
- brcmf_remove_interface(ifp);
return 0;
}