Files
wifipineapple-openwrt/package/kernel/mac80211/patches/393-0002-brcmfmac-correct-interface-combination-info.patch
Rafał Miłecki ae82d6b9e6 mac80211: update brcmfmac to the latest version
This also adds one patchset of pending changes that fix support for
multiple interfaces. It was somehow broken.
Driver couldn't correctly match firmware and system interfaces resulting
in not working APs and WARNINGs.

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

git-svn-id: svn://svn.openwrt.org/openwrt/branches/chaos_calmer@46736 3c298f89-4303-0410-b956-a3cf2f4a3e73
2015-08-26 22:57:54 +00:00

205 lines
6.0 KiB
Diff

From: Arend van Spriel <arend@broadcom.com>
Date: Thu, 20 Aug 2015 22:06:03 +0200
Subject: [PATCH] brcmfmac: correct interface combination info
The interface combination provided by brcmfmac did not truly reflect
the combinations supported by driver and/or firmware.
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: Pontus Fuchs <pontusf@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
---
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
@@ -5694,63 +5694,132 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
}
};
+/**
+ * brcmf_setup_ifmodes() - determine interface modes and combinations.
+ *
+ * @wiphy: wiphy object.
+ * @ifp: interface object needed for feat module api.
+ *
+ * The interface modes and combinations are determined dynamically here
+ * based on firmware functionality.
+ *
+ * no p2p and no mbss:
+ *
+ * #STA <= 1, #AP <= 1, channels = 1, 2 total
+ *
+ * no p2p and mbss:
+ *
+ * #STA <= 1, #AP <= 1, channels = 1, 2 total
+ * #AP <= 4, matching BI, channels = 1, 4 total
+ *
+ * p2p, no mchan, and mbss:
+ *
+ * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total
+ * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
+ * #AP <= 4, matching BI, channels = 1, 4 total
+ *
+ * p2p, mchan, and mbss:
+ *
+ * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total
+ * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
+ * #AP <= 4, matching BI, channels = 1, 4 total
+ */
static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
{
struct ieee80211_iface_combination *combo = NULL;
- struct ieee80211_iface_limit *limits = NULL;
- int i = 0, max_iface_cnt;
+ struct ieee80211_iface_limit *c0_limits = NULL;
+ struct ieee80211_iface_limit *p2p_limits = NULL;
+ struct ieee80211_iface_limit *mbss_limits = NULL;
+ bool mbss, p2p;
+ int i, c, n_combos;
- combo = kzalloc(sizeof(*combo), GFP_KERNEL);
+ mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);
+ p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);
+
+ n_combos = 1 + !!p2p + !!mbss;
+ combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL);
if (!combo)
goto err;
- limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
- if (!limits)
+ c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL);
+ if (!c0_limits)
goto err;
+ if (p2p) {
+ p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL);
+ if (!p2p_limits)
+ goto err;
+ }
+
+ if (mbss) {
+ mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL);
+ if (!mbss_limits)
+ goto err;
+ }
+
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_AP);
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
- combo->num_different_channels = 2;
- else
- combo->num_different_channels = 1;
-
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
- limits[i].max = 1;
- limits[i++].types = BIT(NL80211_IFTYPE_STATION);
- limits[i].max = 4;
- limits[i++].types = BIT(NL80211_IFTYPE_AP);
- max_iface_cnt = 5;
- } else {
- limits[i].max = 2;
- limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP);
- max_iface_cnt = 2;
- }
-
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
+ c = 0;
+ i = 0;
+ combo[c].num_different_channels = 1;
+ c0_limits[i].max = 1;
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+ if (p2p) {
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+ combo[c].num_different_channels = 2;
wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_DEVICE);
- limits[i].max = 1;
- limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_P2P_GO);
- limits[i].max = 1;
- limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
- max_iface_cnt += 2;
- }
- combo->max_interfaces = max_iface_cnt;
- combo->limits = limits;
- combo->n_limits = i;
+ c0_limits[i].max = 1;
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+ c0_limits[i].max = 1;
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO);
+ } else {
+ c0_limits[i].max = 1;
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+ }
+ combo[c].max_interfaces = i;
+ combo[c].n_limits = i;
+ combo[c].limits = c0_limits;
+
+ if (p2p) {
+ c++;
+ i = 0;
+ combo[c].num_different_channels = 1;
+ p2p_limits[i].max = 1;
+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+ p2p_limits[i].max = 1;
+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+ p2p_limits[i].max = 1;
+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT);
+ p2p_limits[i].max = 1;
+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+ combo[c].max_interfaces = i;
+ combo[c].n_limits = i;
+ combo[c].limits = p2p_limits;
+ }
+ if (mbss) {
+ c++;
+ combo[c].beacon_int_infra_match = true;
+ combo[c].num_different_channels = 1;
+ mbss_limits[0].max = 4;
+ mbss_limits[0].types = BIT(NL80211_IFTYPE_AP);
+ combo[c].max_interfaces = 4;
+ combo[c].n_limits = 1;
+ combo[c].limits = mbss_limits;
+ }
+ wiphy->n_iface_combinations = n_combos;
wiphy->iface_combinations = combo;
- wiphy->n_iface_combinations = 1;
return 0;
err:
- kfree(limits);
+ kfree(c0_limits);
+ kfree(p2p_limits);
+ kfree(mbss_limits);
kfree(combo);
return -ENOMEM;
}
@@ -6079,11 +6148,15 @@ static void brcmf_cfg80211_reg_notifier(
static void brcmf_free_wiphy(struct wiphy *wiphy)
{
+ int i;
+
if (!wiphy)
return;
- if (wiphy->iface_combinations)
- kfree(wiphy->iface_combinations->limits);
+ if (wiphy->iface_combinations) {
+ for (i = 0; i < wiphy->n_iface_combinations; i++)
+ kfree(wiphy->iface_combinations[i].limits);
+ }
kfree(wiphy->iface_combinations);
if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);