mirror of https://github.com/hak5/openwrt-owl.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 <zajec5@gmail.com> SVN-Revision: 46724owl
parent
13a095085e
commit
7a68c31a81
|
@ -0,0 +1,45 @@
|
||||||
|
From: Vineet Gupta <Vineet.Gupta1@synopsys.com>
|
||||||
|
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 <kvalo@codeaurora.org>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- 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);
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||||
|
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 <zajec5@gmail.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
|
||||||
|
@@ -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);
|
|
@ -0,0 +1,204 @@
|
||||||
|
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
|
||||||
|
@@ -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);
|
|
@ -0,0 +1,87 @@
|
||||||
|
From: Franky Lin <frankyl@broadcom.com>
|
||||||
|
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 <arend@broadcom.com>
|
||||||
|
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||||
|
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||||
|
Signed-off-by: Franky Lin <frankyl@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/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:
|
|
@ -0,0 +1,83 @@
|
||||||
|
From: Arend van Spriel <arend@broadcom.com>
|
||||||
|
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 <meuleman@broadcom.com>
|
||||||
|
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||||
|
Reviewed-by: Pieter-Paul Giesberts <pieterpg@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
|
||||||
|
@@ -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:
|
|
@ -0,0 +1,48 @@
|
||||||
|
From: Franky Lin <frankyl@broadcom.com>
|
||||||
|
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 <pieterpg@broadcom.com>
|
||||||
|
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||||
|
Signed-off-by: Franky Lin <frankyl@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/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;
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
From: Arend van Spriel <arend@broadcom.com>
|
||||||
|
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 <pontusf@broadcom.com>
|
||||||
|
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/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
|
||||||
|
|
|
@ -10,12 +10,13 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||||
|
|
||||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||||
+++ b/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,
|
u32 *flags,
|
||||||
struct vif_params *params)
|
struct vif_params *params)
|
||||||
{
|
{
|
||||||
+ struct net_device *dev;
|
+ struct net_device *dev;
|
||||||
struct wireless_dev *wdev;
|
struct wireless_dev *wdev;
|
||||||
|
int err;
|
||||||
|
|
||||||
+ /*
|
+ /*
|
||||||
+ * There is a bug with in-firmware BSS management. When adding virtual
|
+ * There is a bug with in-firmware BSS management. When adding virtual
|
||||||
|
@ -45,5 +46,5 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
|
brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
|
||||||
switch (type) {
|
err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
|
||||||
case NL80211_IFTYPE_ADHOC:
|
if (err) {
|
||||||
|
|
Loading…
Reference in New Issue