From: Rafał Miłecki Date: Tue, 25 Aug 2015 15:20:48 +0000 (+0000) Subject: mac80211: backport latest patches except for NVRAM support X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=7a68c31a819ee640e529b629f1457ab0b87add6b;p=librecmc%2Flibrecmc.git mac80211: backport latest patches except for NVRAM support We sill don't use kernel 4.2 which is required for backporting using upstream NVRAM support patch. Signed-off-by: Rafał Miłecki SVN-Revision: 46724 --- diff --git a/package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch b/package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch new file mode 100644 index 0000000000..e44f121ea3 --- /dev/null +++ b/package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch @@ -0,0 +1,45 @@ +From: Vineet Gupta +Date: Thu, 9 Jul 2015 13:43:18 +0530 +Subject: [PATCH] brcmfmac: dhd_sdio.c: use existing atomic_or primitive + +There's already a generic implementation so use that instead. + +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +@@ -2564,15 +2564,6 @@ static inline void brcmf_sdio_clrintr(st + } + } + +-static void atomic_orr(int val, atomic_t *v) +-{ +- int old_val; +- +- old_val = atomic_read(v); +- while (atomic_cmpxchg(v, old_val, val | old_val) != old_val) +- old_val = atomic_read(v); +-} +- + static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) + { + struct brcmf_core *buscore; +@@ -2595,7 +2586,7 @@ static int brcmf_sdio_intr_rstatus(struc + if (val) { + brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret); + bus->sdcnt.f1regdata++; +- atomic_orr(val, &bus->intstatus); ++ atomic_or(val, &bus->intstatus); + } + + return ret; +@@ -2712,7 +2703,7 @@ static void brcmf_sdio_dpc(struct brcmf_ + + /* Keep still-pending events for next scheduling */ + if (intstatus) +- atomic_orr(intstatus, &bus->intstatus); ++ atomic_or(intstatus, &bus->intstatus); + + brcmf_sdio_clrintr(bus); + diff --git a/package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch b/package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch new file mode 100644 index 0000000000..bb27115d19 --- /dev/null +++ b/package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch @@ -0,0 +1,46 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 20 Aug 2015 00:16:42 +0200 +Subject: [PATCH] brcmfmac: check all combinations when setting wiphy's + addresses +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Broadcom is working on better reflection of interface combinations. With +upcoming patches we may have 1st combination supporting less interfaces +than others. +To don't run out of addresses check all combinations to find the one +with the greatest max_interfaces value. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +@@ -5786,7 +5786,9 @@ static void brcmf_wiphy_wowl_params(stru + static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) + { + struct brcmf_pub *drvr = ifp->drvr; ++ const struct ieee80211_iface_combination *combo; + struct ieee80211_supported_band *band; ++ u16 max_interfaces = 0; + __le32 bandlist[3]; + u32 n_bands; + int err, i; +@@ -5799,8 +5801,13 @@ static int brcmf_setup_wiphy(struct wiph + if (err) + return err; + +- for (i = 0; i < wiphy->iface_combinations->max_interfaces && +- i < ARRAY_SIZE(drvr->addresses); i++) { ++ for (i = 0, combo = wiphy->iface_combinations; ++ i < wiphy->n_iface_combinations; i++, combo++) { ++ max_interfaces = max(max_interfaces, combo->max_interfaces); ++ } ++ ++ for (i = 0; i < max_interfaces && i < ARRAY_SIZE(drvr->addresses); ++ i++) { + u8 *addr = drvr->addresses[i].addr; + + memcpy(addr, drvr->mac, ETH_ALEN); 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); diff --git a/package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch b/package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch new file mode 100644 index 0000000000..9768ef2771 --- /dev/null +++ b/package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch @@ -0,0 +1,87 @@ +From: Franky Lin +Date: Thu, 20 Aug 2015 22:06:04 +0200 +Subject: [PATCH] brcmfmac: add debugfs entry for msgbuf statistics + +Expose ring buffer read/write pointers and other useful statistics +through debugfs. + +Reviewed-by: Arend Van Spriel +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Signed-off-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +@@ -1360,6 +1360,60 @@ void brcmf_msgbuf_delete_flowring(struct + } + } + ++#ifdef DEBUG ++static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data) ++{ ++ struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); ++ struct brcmf_pub *drvr = bus_if->drvr; ++ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; ++ struct brcmf_commonring *commonring; ++ u16 i; ++ struct brcmf_flowring_ring *ring; ++ struct brcmf_flowring_hash *hash; ++ ++ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT]; ++ seq_printf(seq, "h2d_ctl_submit: rp %4u, wp %4u, depth %4u\n", ++ commonring->r_ptr, commonring->w_ptr, commonring->depth); ++ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT]; ++ seq_printf(seq, "h2d_rx_submit: rp %4u, wp %4u, depth %4u\n", ++ commonring->r_ptr, commonring->w_ptr, commonring->depth); ++ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE]; ++ seq_printf(seq, "d2h_ctl_cmplt: rp %4u, wp %4u, depth %4u\n", ++ commonring->r_ptr, commonring->w_ptr, commonring->depth); ++ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE]; ++ seq_printf(seq, "d2h_tx_cmplt: rp %4u, wp %4u, depth %4u\n", ++ commonring->r_ptr, commonring->w_ptr, commonring->depth); ++ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE]; ++ seq_printf(seq, "d2h_rx_cmplt: rp %4u, wp %4u, depth %4u\n", ++ commonring->r_ptr, commonring->w_ptr, commonring->depth); ++ ++ seq_printf(seq, "\nh2d_flowrings: depth %u\n", ++ BRCMF_H2D_TXFLOWRING_MAX_ITEM); ++ seq_puts(seq, "Active flowrings:\n"); ++ hash = msgbuf->flow->hash; ++ for (i = 0; i < msgbuf->flow->nrofrings; i++) { ++ if (!msgbuf->flow->rings[i]) ++ continue; ++ ring = msgbuf->flow->rings[i]; ++ if (ring->status != RING_OPEN) ++ continue; ++ commonring = msgbuf->flowrings[i]; ++ hash = &msgbuf->flow->hash[ring->hash_id]; ++ seq_printf(seq, "id %3u: rp %4u, wp %4u, qlen %4u, blocked %u\n" ++ " ifidx %u, fifo %u, da %pM\n", ++ i, commonring->r_ptr, commonring->w_ptr, ++ skb_queue_len(&ring->skblist), ring->blocked, ++ hash->ifidx, hash->fifo, hash->mac); ++ } ++ ++ return 0; ++} ++#else ++static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data) ++{ ++ return 0; ++} ++#endif + + int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) + { +@@ -1460,6 +1514,8 @@ int brcmf_proto_msgbuf_attach(struct brc + spin_lock_init(&msgbuf->flowring_work_lock); + INIT_LIST_HEAD(&msgbuf->work_queue); + ++ brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read); ++ + return 0; + + fail: diff --git a/package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch b/package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch new file mode 100644 index 0000000000..281f02b7dc --- /dev/null +++ b/package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch @@ -0,0 +1,83 @@ +From: Arend van Spriel +Date: Thu, 20 Aug 2015 22:06:05 +0200 +Subject: [PATCH] brcmfmac: make use of cfg80211_check_combinations() + +Use cfg80211_check_combinations() so we can bail out early when an +interface add or change results in an invalid combination. + +Reviewed-by: Hante Meuleman +Reviewed-by: Franky (Zhenhui) Lin +Reviewed-by: Pieter-Paul Giesberts +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 +@@ -469,6 +469,36 @@ brcmf_find_wpsie(const u8 *parse, u32 le + return NULL; + } + ++static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg, ++ struct brcmf_cfg80211_vif *vif, ++ enum nl80211_iftype new_type) ++{ ++ int iftype_num[NUM_NL80211_IFTYPES]; ++ struct brcmf_cfg80211_vif *pos; ++ ++ memset(&iftype_num[0], 0, sizeof(iftype_num)); ++ list_for_each_entry(pos, &cfg->vif_list, list) ++ if (pos == vif) ++ iftype_num[new_type]++; ++ else ++ iftype_num[pos->wdev.iftype]++; ++ ++ return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); ++} ++ ++static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg, ++ enum nl80211_iftype new_type) ++{ ++ int iftype_num[NUM_NL80211_IFTYPES]; ++ struct brcmf_cfg80211_vif *pos; ++ ++ memset(&iftype_num[0], 0, sizeof(iftype_num)); ++ list_for_each_entry(pos, &cfg->vif_list, list) ++ iftype_num[pos->wdev.iftype]++; ++ ++ iftype_num[new_type]++; ++ return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); ++} + + static void convert_key_from_CPU(struct brcmf_wsec_key *key, + struct brcmf_wsec_key_le *key_le) +@@ -663,8 +693,14 @@ static struct wireless_dev *brcmf_cfg802 + struct vif_params *params) + { + struct wireless_dev *wdev; ++ int err; + + brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); ++ err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); ++ if (err) { ++ brcmf_err("iface validation failed: err=%d\n", err); ++ return ERR_PTR(err); ++ } + switch (type) { + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: +@@ -823,8 +859,12 @@ brcmf_cfg80211_change_iface(struct wiphy + s32 ap = 0; + s32 err = 0; + +- brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type); +- ++ brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type); ++ err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type); ++ if (err) { ++ brcmf_err("iface validation failed: err=%d\n", err); ++ return err; ++ } + switch (type) { + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_WDS: diff --git a/package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch b/package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch new file mode 100644 index 0000000000..2d5f7b9be7 --- /dev/null +++ b/package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch @@ -0,0 +1,48 @@ +From: Franky Lin +Date: Thu, 20 Aug 2015 22:06:06 +0200 +Subject: [PATCH] brcmfmac: block the correct flowring when backup queue + overflow + +brcmf_flowring_block blocks the last active flowring under the same +interface instead of the one provided by caller. This could lead to a +dead lock of netif stop if there are more than one flowring under the +interface and the traffic is high enough so brcmf_flowring_enqueue can +not unblock the ring right away. + +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Hante Meuleman +Signed-off-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +@@ -194,11 +194,15 @@ static void brcmf_flowring_block(struct + spin_lock_irqsave(&flow->block_lock, flags); + + ring = flow->rings[flowid]; ++ if (ring->blocked == blocked) { ++ spin_unlock_irqrestore(&flow->block_lock, flags); ++ return; ++ } + ifidx = brcmf_flowring_ifidx_get(flow, flowid); + + currently_blocked = false; + for (i = 0; i < flow->nrofrings; i++) { +- if (flow->rings[i]) { ++ if ((flow->rings[i]) && (i != flowid)) { + ring = flow->rings[i]; + if ((ring->status == RING_OPEN) && + (brcmf_flowring_ifidx_get(flow, i) == ifidx)) { +@@ -209,8 +213,8 @@ static void brcmf_flowring_block(struct + } + } + } +- ring->blocked = blocked; +- if (currently_blocked == blocked) { ++ flow->rings[flowid]->blocked = blocked; ++ if (currently_blocked) { + spin_unlock_irqrestore(&flow->block_lock, flags); + return; + } diff --git a/package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch b/package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch new file mode 100644 index 0000000000..7378401c52 --- /dev/null +++ b/package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch @@ -0,0 +1,52 @@ +From: Arend van Spriel +Date: Thu, 20 Aug 2015 22:06:07 +0200 +Subject: [PATCH] brcmfmac: bump highest event number for 4339 firmware + +The event mask length is determined by the highest event number +that is specified in the driver. When this length is shorter than +firmware expects setting event mask will fail and device becomes +pretty useless. This issue was reported with bcm4339 firmware that +was recently released. + +Reported-by: Pontus Fuchs +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/fweh.h ++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +@@ -85,7 +85,6 @@ struct brcmf_event; + BRCMF_ENUM_DEF(IF, 54) \ + BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \ + BRCMF_ENUM_DEF(RSSI, 56) \ +- BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \ + BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \ + BRCMF_ENUM_DEF(ACTION_FRAME, 59) \ + BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \ +@@ -103,8 +102,7 @@ struct brcmf_event; + BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \ + BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \ + BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \ +- BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \ +- BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128) ++ BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) + + #define BRCMF_ENUM_DEF(id, val) \ + BRCMF_E_##id = (val), +@@ -112,7 +110,11 @@ struct brcmf_event; + /* firmware event codes sent by the dongle */ + enum brcmf_fweh_event_code { + BRCMF_FWEH_EVENT_ENUM_DEFLIST +- BRCMF_E_LAST ++ /* this determines event mask length which must match ++ * minimum length check in device firmware so it is ++ * hard-coded here. ++ */ ++ BRCMF_E_LAST = 139 + }; + #undef BRCMF_ENUM_DEF + diff --git a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch index 49b223d724..5fdfa37277 100644 --- a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch +++ b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch @@ -10,12 +10,13 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -@@ -662,8 +662,36 @@ static struct wireless_dev *brcmf_cfg802 +@@ -692,9 +692,37 @@ static struct wireless_dev *brcmf_cfg802 u32 *flags, struct vif_params *params) { + struct net_device *dev; struct wireless_dev *wdev; + int err; + /* + * There is a bug with in-firmware BSS management. When adding virtual @@ -45,5 +46,5 @@ Signed-off-by: Rafał Miłecki + } + brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); - switch (type) { - case NL80211_IFTYPE_ADHOC: + err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); + if (err) {