From 5d9d3ee389e30264f741b4bba5a09d1d9cc0ecbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 25 Aug 2015 15:20:48 +0000 Subject: mac80211: backport latest patches except for NVRAM support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We sill don't use kernel 4.2 which is required for backporting using upstream NVRAM support patch. Signed-off-by: Rafał Miłecki git-svn-id: svn://svn.openwrt.org/openwrt/trunk@46724 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- ...cmfmac-correct-interface-combination-info.patch | 204 +++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch (limited to 'package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch') diff --git a/package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch b/package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch new file mode 100644 index 0000000000..baee295cd5 --- /dev/null +++ b/package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch @@ -0,0 +1,204 @@ +From: Arend van Spriel +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 +Reviewed-by: Franky (Zhenhui) Lin +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Pontus Fuchs +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +@@ -5695,63 +5695,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; + } +@@ -6080,11 +6149,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); -- cgit v1.2.3