mac80211: backport latest patches except for NVRAM support
authorRafał Miłecki <zajec5@gmail.com>
Tue, 25 Aug 2015 15:20:48 +0000 (15:20 +0000)
committerRafał Miłecki <zajec5@gmail.com>
Tue, 25 Aug 2015 15:20:48 +0000 (15:20 +0000)
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: 46724

package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch [new file with mode: 0644]
package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch [new file with mode: 0644]
package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch [new file with mode: 0644]
package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch [new file with mode: 0644]
package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch [new file with mode: 0644]
package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch [new file with mode: 0644]
package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch [new file with mode: 0644]
package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch

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 (file)
index 0000000..e44f121
--- /dev/null
@@ -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);
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 (file)
index 0000000..bb27115
--- /dev/null
@@ -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);
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 (file)
index 0000000..baee295
--- /dev/null
@@ -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);
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 (file)
index 0000000..9768ef2
--- /dev/null
@@ -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:
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 (file)
index 0000000..281f02b
--- /dev/null
@@ -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:
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 (file)
index 0000000..2d5f7b9
--- /dev/null
@@ -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;
+       }
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 (file)
index 0000000..7378401
--- /dev/null
@@ -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
index 49b223d..5fdfa37 100644 (file)
@@ -10,12 +10,13 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 
 --- 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 <zajec5@gmail.com>
 +      }
 +
        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) {