mirror of
https://github.com/hak5/wifipineapple-openwrt.git
synced 2025-10-29 16:57:19 +00:00
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
205 lines
6.0 KiB
Diff
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);
|