ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/package/kernel/mac80211/patches/brcm/040-brcmutil_option.patch b/package/kernel/mac80211/patches/brcm/040-brcmutil_option.patch
new file mode 100644
index 0000000..3e8505b
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/040-brcmutil_option.patch
@@ -0,0 +1,10 @@
+--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
++++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
+@@ -1,6 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ config BRCMUTIL
+-	tristate
++	tristate "Broadcom 802.11 driver utility functions"
+ 	depends on m
+ 
+ config BRCMSMAC
diff --git a/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch b/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch
new file mode 100644
index 0000000..09ef505
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch
@@ -0,0 +1,37 @@
+--- a/drivers/net/wireless/broadcom/b43/b43.h
++++ b/drivers/net/wireless/broadcom/b43/b43.h
+@@ -840,6 +840,7 @@ struct b43_wldev {
+ 	bool qos_enabled;		/* TRUE, if QoS is used. */
+ 	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
+ 	bool use_pio;			/* TRUE if next init should use PIO */
++	int gpiomask;			/* GPIO LED mask as a module parameter */
+ 
+ 	/* PHY/Radio device. */
+ 	struct b43_phy phy;
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -72,6 +72,11 @@ MODULE_FIRMWARE("b43/ucode40.fw");
+ MODULE_FIRMWARE("b43/ucode42.fw");
+ MODULE_FIRMWARE("b43/ucode9.fw");
+ 
++static int modparam_gpiomask = 0x000F;
++module_param_named(gpiomask, modparam_gpiomask, int, 0444);
++MODULE_PARM_DESC(gpiomask,
++         "GPIO mask for LED control (default 0x000F)");
++
+ static int modparam_bad_frames_preempt;
+ module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+ MODULE_PARM_DESC(bad_frames_preempt,
+@@ -2869,10 +2874,10 @@ static int b43_gpio_init(struct b43_wlde
+ 	u32 mask, set;
+ 
+ 	b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
+-	b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF);
++	b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, modparam_gpiomask);
+ 
+ 	mask = 0x0000001F;
+-	set = 0x0000000F;
++	set = modparam_gpiomask;
+ 	if (dev->dev->chip_id == 0x4301) {
+ 		mask |= 0x0060;
+ 		set |= 0x0060;
diff --git a/package/kernel/mac80211/patches/brcm/811-b43_no_pio.patch b/package/kernel/mac80211/patches/brcm/811-b43_no_pio.patch
new file mode 100644
index 0000000..e395d48
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/811-b43_no_pio.patch
@@ -0,0 +1,86 @@
+--- a/drivers/net/wireless/broadcom/b43/Makefile
++++ b/drivers/net/wireless/broadcom/b43/Makefile
+@@ -18,7 +18,7 @@ b43-$(CPTCFG_B43_PHY_AC)	+= phy_ac.o
+ b43-y				+= sysfs.o
+ b43-y				+= xmit.o
+ b43-y				+= dma.o
+-b43-y				+= pio.o
++b43-$(CPTCFG_B43_PIO)		+= pio.o
+ b43-y				+= rfkill.o
+ b43-y				+= ppr.o
+ b43-$(CPTCFG_B43_LEDS)		+= leds.o
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -2001,10 +2001,12 @@ static void b43_do_interrupt_thread(stru
+ 			dma_reason[0], dma_reason[1],
+ 			dma_reason[2], dma_reason[3],
+ 			dma_reason[4], dma_reason[5]);
++#ifdef CPTCFG_B43_PIO
+ 		b43err(dev->wl, "This device does not support DMA "
+ 			       "on your system. It will now be switched to PIO.\n");
+ 		/* Fall back to PIO transfers if we get fatal DMA errors! */
+ 		dev->use_pio = true;
++#endif
+ 		b43_controller_restart(dev, "DMA error");
+ 		return;
+ 	}
+--- a/drivers/net/wireless/broadcom/b43/pio.h
++++ b/drivers/net/wireless/broadcom/b43/pio.h
+@@ -151,7 +151,7 @@ static inline void b43_piorx_write32(str
+ 	b43_write32(q->dev, q->mmio_base + offset, value);
+ }
+ 
+-
++#ifdef CPTCFG_B43_PIO
+ int b43_pio_init(struct b43_wldev *dev);
+ void b43_pio_free(struct b43_wldev *dev);
+ 
+@@ -162,5 +162,37 @@ void b43_pio_rx(struct b43_pio_rxqueue *
+ 
+ void b43_pio_tx_suspend(struct b43_wldev *dev);
+ void b43_pio_tx_resume(struct b43_wldev *dev);
++#else
++static inline int b43_pio_init(struct b43_wldev *dev)
++{
++	return 0;
++}
++
++static inline void b43_pio_free(struct b43_wldev *dev)
++{
++}
++
++static inline int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
++{
++	return 0;
++}
++
++static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
++					   const struct b43_txstatus *status)
++{
++}
++
++static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
++{
++}
++
++static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
++{
++}
++
++static inline void b43_pio_tx_resume(struct b43_wldev *dev)
++{
++}
++#endif /* CPTCFG_B43_PIO */
+ 
+ #endif /* B43_PIO_H_ */
+--- a/drivers/net/wireless/broadcom/b43/Kconfig
++++ b/drivers/net/wireless/broadcom/b43/Kconfig
+@@ -100,7 +100,7 @@ config B43_BCMA_PIO
+ 	default y
+ 
+ config B43_PIO
+-	bool
++	bool "Broadcom 43xx PIO support"
+ 	depends on B43 && B43_SSB
+ 	depends on SSB_BLOCKIO
+ 	default y
diff --git a/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch b/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch
new file mode 100644
index 0000000..52ae7a8
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch
@@ -0,0 +1,131 @@
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -1643,7 +1643,7 @@ static void b43_write_beacon_template(st
+ 				  len, ram_offset, shm_size_offset, rate);
+ 
+ 	/* Write the PHY TX control parameters. */
+-	antenna = B43_ANTENNA_DEFAULT;
++	antenna = dev->tx_antenna;
+ 	antenna = b43_antenna_to_phyctl(antenna);
+ 	ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
+ 	/* We can't send beacons with short preamble. Would get PHY errors. */
+@@ -3284,8 +3284,8 @@ static int b43_chip_init(struct b43_wlde
+ 
+ 	/* Select the antennae */
+ 	if (phy->ops->set_rx_antenna)
+-		phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
+-	b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
++		phy->ops->set_rx_antenna(dev, dev->rx_antenna);
++	b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+ 
+ 	if (phy->type == B43_PHYTYPE_B) {
+ 		value16 = b43_read16(dev, 0x005E);
+@@ -3985,7 +3985,6 @@ static int b43_op_config(struct ieee8021
+ 	struct b43_wldev *dev = wl->current_dev;
+ 	struct b43_phy *phy = &dev->phy;
+ 	struct ieee80211_conf *conf = &hw->conf;
+-	int antenna;
+ 	int err = 0;
+ 
+ 	mutex_lock(&wl->mutex);
+@@ -4028,11 +4027,9 @@ static int b43_op_config(struct ieee8021
+ 	}
+ 
+ 	/* Antennas for RX and management frame TX. */
+-	antenna = B43_ANTENNA_DEFAULT;
+-	b43_mgmtframe_txantenna(dev, antenna);
+-	antenna = B43_ANTENNA_DEFAULT;
++	b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+ 	if (phy->ops->set_rx_antenna)
+-		phy->ops->set_rx_antenna(dev, antenna);
++		phy->ops->set_rx_antenna(dev, dev->rx_antenna);
+ 
+ 	if (wl->radio_enabled != phy->radio_on) {
+ 		if (wl->radio_enabled) {
+@@ -5176,6 +5173,47 @@ static int b43_op_get_survey(struct ieee
+ 	return 0;
+ }
+ 
++static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
++{
++	struct b43_wl *wl = hw_to_b43_wl(hw);
++	struct b43_wldev *dev = wl->current_dev;
++
++	if (tx_ant == 1 && rx_ant == 1) {
++		dev->tx_antenna = B43_ANTENNA0;
++		dev->rx_antenna = B43_ANTENNA0;
++	}
++	else if (tx_ant == 2 && rx_ant == 2) {
++		dev->tx_antenna = B43_ANTENNA1;
++		dev->rx_antenna = B43_ANTENNA1;
++	}
++	else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) {
++		dev->tx_antenna = B43_ANTENNA_DEFAULT;
++		dev->rx_antenna = B43_ANTENNA_DEFAULT;
++	}
++	else {
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++
++static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
++{
++	struct b43_wl *wl = hw_to_b43_wl(hw);
++	struct b43_wldev *dev = wl->current_dev;
++
++	switch (dev->tx_antenna) {
++	case B43_ANTENNA0:
++		*tx_ant = 1; *rx_ant = 1; break;
++	case B43_ANTENNA1:
++		*tx_ant = 2; *rx_ant = 2; break;
++	case B43_ANTENNA_DEFAULT:
++		*tx_ant = 3; *rx_ant = 3; break;
++	}
++	return 0;
++}
++
+ static const struct ieee80211_ops b43_hw_ops = {
+ 	.tx			= b43_op_tx,
+ 	.conf_tx		= b43_op_conf_tx,
+@@ -5197,6 +5235,8 @@ static const struct ieee80211_ops b43_hw
+ 	.sw_scan_complete	= b43_op_sw_scan_complete_notifier,
+ 	.get_survey		= b43_op_get_survey,
+ 	.rfkill_poll		= b43_rfkill_poll,
++	.set_antenna		= b43_op_set_antenna,
++	.get_antenna		= b43_op_get_antenna,
+ };
+ 
+ /* Hard-reset the chip. Do not call this directly.
+@@ -5498,6 +5538,8 @@ static int b43_one_core_attach(struct b4
+ 	if (!wldev)
+ 		goto out;
+ 
++	wldev->rx_antenna = B43_ANTENNA_DEFAULT;
++	wldev->tx_antenna = B43_ANTENNA_DEFAULT;
+ 	wldev->use_pio = b43_modparam_pio;
+ 	wldev->dev = dev;
+ 	wldev->wl = wl;
+@@ -5592,6 +5634,9 @@ static struct b43_wl *b43_wireless_init(
+ 
+ 	wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+ 
++	hw->wiphy->available_antennas_rx = 0x3;
++	hw->wiphy->available_antennas_tx = 0x3;
++
+ 	wl->hw_registered = false;
+ 	hw->max_rates = 2;
+ 	SET_IEEE80211_DEV(hw, dev->dev);
+--- a/drivers/net/wireless/broadcom/b43/b43.h
++++ b/drivers/net/wireless/broadcom/b43/b43.h
+@@ -841,6 +841,8 @@ struct b43_wldev {
+ 	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
+ 	bool use_pio;			/* TRUE if next init should use PIO */
+ 	int gpiomask;			/* GPIO LED mask as a module parameter */
++	int rx_antenna;			/* Used RX antenna (B43_ANTENNAxxx) */
++	int tx_antenna;			/* Used TX antenna (B43_ANTENNAxxx) */
+ 
+ 	/* PHY/Radio device. */
+ 	struct b43_phy phy;
diff --git a/package/kernel/mac80211/patches/brcm/813-b43-reduce-number-of-RX-slots.patch b/package/kernel/mac80211/patches/brcm/813-b43-reduce-number-of-RX-slots.patch
new file mode 100644
index 0000000..85c52c0
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/813-b43-reduce-number-of-RX-slots.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/broadcom/b43/dma.h
++++ b/drivers/net/wireless/broadcom/b43/dma.h
+@@ -170,7 +170,7 @@ struct b43_dmadesc_generic {
+ 
+ /* DMA engine tuning knobs */
+ #define B43_TXRING_SLOTS		256
+-#define B43_RXRING_SLOTS		256
++#define B43_RXRING_SLOTS		32
+ #define B43_DMA0_RX_FW598_BUFSIZE	(B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
+ #define B43_DMA0_RX_FW351_BUFSIZE	(B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
+ 
diff --git a/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch b/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch
new file mode 100644
index 0000000..9cb0a32
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch
@@ -0,0 +1,17 @@
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -2886,6 +2886,14 @@ static int b43_gpio_init(struct b43_wlde
+ 	} else if (dev->dev->chip_id == 0x5354) {
+ 		/* Don't allow overtaking buttons GPIOs */
+ 		set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */
++	} else if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 || 
++		   dev->dev->chip_id == BCMA_CHIP_ID_BCM47162 ||
++		   dev->dev->chip_id == BCMA_CHIP_ID_BCM5356 ||
++		   dev->dev->chip_id == BCMA_CHIP_ID_BCM5357 ||
++		   dev->dev->chip_id == BCMA_CHIP_ID_BCM53572) {
++		/* just use gpio 0 and 1 for 2.4 GHz wifi led */
++		set &= 0x3;
++		mask &= 0x3;
+ 	}
+ 
+ 	if (0 /* FIXME: conditional unknown */ ) {
diff --git a/package/kernel/mac80211/patches/brcm/815-b43-always-take-overlapping-devs.patch b/package/kernel/mac80211/patches/brcm/815-b43-always-take-overlapping-devs.patch
new file mode 100644
index 0000000..a8eae19
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/815-b43-always-take-overlapping-devs.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -114,7 +114,7 @@ static int b43_modparam_pio = 0;
+ module_param_named(pio, b43_modparam_pio, int, 0644);
+ MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
+ 
+-static int modparam_allhwsupport = !IS_ENABLED(CPTCFG_BRCMSMAC);
++static int modparam_allhwsupport = 1;
+ module_param_named(allhwsupport, modparam_allhwsupport, int, 0444);
+ MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)");
+ 
diff --git a/package/kernel/mac80211/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch b/package/kernel/mac80211/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch
new file mode 100644
index 0000000..3c93386
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch
@@ -0,0 +1,27 @@
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
+@@ -58,19 +58,12 @@
+ 				 (((c) < 149) ? 3 : 4))))
+ 
+ #define BRCM_2GHZ_2412_2462	REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
+-#define BRCM_2GHZ_2467_2472	REG_RULE(2467-10, 2472+10, 20, 0, 19, \
+-					 NL80211_RRF_NO_IR)
++#define BRCM_2GHZ_2467_2472	REG_RULE(2467-10, 2472+10, 20, 0, 19, 0)
+ 
+-#define BRCM_5GHZ_5180_5240	REG_RULE(5180-10, 5240+10, 40, 0, 21, \
+-					 NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5260_5320	REG_RULE(5260-10, 5320+10, 40, 0, 21, \
+-					 NL80211_RRF_DFS | \
+-					 NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5500_5700	REG_RULE(5500-10, 5700+10, 40, 0, 21, \
+-					 NL80211_RRF_DFS | \
+-					 NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5745_5825	REG_RULE(5745-10, 5825+10, 40, 0, 21, \
+-					 NL80211_RRF_NO_IR)
++#define BRCM_5GHZ_5180_5240	REG_RULE(5180-10, 5240+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5260_5320	REG_RULE(5260-10, 5320+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5500_5700	REG_RULE(5500-10, 5700+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5745_5825	REG_RULE(5745-10, 5825+10, 40, 0, 21, 0)
+ 
+ static const struct ieee80211_regdomain brcms_regdom_x2 = {
+ 	.n_reg_rules = 6,
diff --git a/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch
new file mode 100644
index 0000000..4f72e62
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch
@@ -0,0 +1,64 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Mon, 8 Jun 2015 16:11:40 +0200
+Subject: [PATCH] brcmfmac: register wiphy(s) during module_init
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is needed by OpenWrt which expects all PHYs to be created after
+module loads successfully.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+@@ -433,6 +433,7 @@ struct brcmf_fw {
+ 	struct brcmf_fw_request *req;
+ 	u32 curpos;
+ 	void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
++	struct completion *completion;
+ };
+ 
+ static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
+@@ -640,6 +641,8 @@ static void brcmf_fw_request_done(const
+ 		fwctx->req = NULL;
+ 	}
+ 	fwctx->done(fwctx->dev, ret, fwctx->req);
++	if (fwctx->completion)
++		complete(fwctx->completion);
+ 	kfree(fwctx);
+ }
+ 
+@@ -664,6 +667,8 @@ int brcmf_fw_get_firmwares(struct device
+ {
+ 	struct brcmf_fw_item *first = &req->items[0];
+ 	struct brcmf_fw *fwctx;
++	struct completion completion;
++	unsigned long time_left;
+ 	int ret;
+ 
+ 	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
+@@ -680,6 +685,9 @@ int brcmf_fw_get_firmwares(struct device
+ 	fwctx->dev = dev;
+ 	fwctx->req = req;
+ 	fwctx->done = fw_cb;
++ 
++	init_completion(&completion);
++	fwctx->completion = &completion;
+ 
+ 	ret = request_firmware_nowait(THIS_MODULE, true, first->path,
+ 				      fwctx->dev, GFP_KERNEL, fwctx,
+@@ -687,6 +695,12 @@ int brcmf_fw_get_firmwares(struct device
+ 	if (ret < 0)
+ 		brcmf_fw_request_done(NULL, fwctx);
+ 
++
++	time_left = wait_for_completion_timeout(&completion,
++						msecs_to_jiffies(5000));
++	if (!time_left && fwctx)
++		fwctx->completion = NULL;
++
+ 	return 0;
+ }
+ 
diff --git a/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
new file mode 100644
index 0000000..e832f17
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
@@ -0,0 +1,49 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Thu, 9 Jul 2015 00:07:59 +0200
+Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -718,8 +718,36 @@ static struct wireless_dev *brcmf_cfg802
+ 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ 	struct brcmf_pub *drvr = cfg->pub;
+ 	struct wireless_dev *wdev;
++	struct net_device *dev;
+ 	int err;
+ 
++	/*
++	 * There is a bug with in-firmware BSS management. When adding virtual
++	 * interface brcmfmac first tells firmware to create new BSS and then
++	 * it creates new struct net_device.
++	 *
++	 * If creating/registering netdev(ice) fails, BSS remains in some bugged
++	 * state. It conflicts with existing BSSes by overtaking their auth
++	 * requests.
++	 *
++	 * It results in one BSS (addresss X) sending beacons and another BSS
++	 * (address Y) replying to authentication requests. This makes interface
++	 * unusable as AP.
++	 *
++	 * To workaround this bug we may try to guess if register_netdev(ice)
++	 * will fail. The most obvious case is using interface name that already
++	 * exists. This is actually quite likely with brcmfmac & some user space
++	 * scripts as brcmfmac doesn't allow deleting virtual interfaces.
++	 * So this bug can be triggered even by something trivial like:
++	 * iw dev wlan0 delete
++	 * iw phy phy0 interface add wlan0 type __ap
++	 */
++	dev = dev_get_by_name(&init_net, name);
++	if (dev) {
++		dev_put(dev);
++		return ERR_PTR(-ENFILE);
++	}
++
+ 	brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
+ 	err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
+ 	if (err) {
diff --git a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch
new file mode 100644
index 0000000..d6e2c40
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch
@@ -0,0 +1,27 @@
+From 66ae1b1750720a33e29792a177b1e696f4f005fb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 9 Mar 2016 17:25:59 +0000
+Subject: [PATCH] brcmfmac: Disable power management
+
+Disable wireless power saving in the brcmfmac WLAN driver. This is a
+temporary measure until the connectivity loss resulting from power
+saving is resolved.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -2964,6 +2964,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
+ 	 * preference in cfg struct to apply this to
+ 	 * FW later while initializing the dongle
+ 	 */
++#if defined(CONFIG_ARCH_BCM2835)
++	brcmf_dbg(INFO, "power management disabled\n");
++	enabled = false;
++#endif
+ 	cfg->pwr_save = enabled;
+ 	if (!check_vif_up(ifp->vif)) {
+ 
diff --git a/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch b/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch
new file mode 100644
index 0000000..9658bda
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch
@@ -0,0 +1,60 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Subject: [PATCH] brcmfmac: add in-driver tables with country codes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This adds early support for changing region. Ideally this data should
+be stored in DT as all these mappings are devices specific.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+@@ -12,6 +12,36 @@
+ #include "common.h"
+ #include "of.h"
+ 
++/* TODO: FIXME: Use DT */
++static void brcmf_of_probe_cc(struct device *dev,
++			      struct brcmf_mp_device *settings)
++{
++	static struct brcmfmac_pd_cc_entry netgear_r8000_cc_ent[] = {
++		{ "JP", "JP", 78 },
++		{ "US", "Q2", 86 },
++	};
++	struct brcmfmac_pd_cc_entry *cc_ent = NULL;
++	int table_size = 0;
++
++	if (of_machine_is_compatible("netgear,r8000")) {
++		cc_ent = netgear_r8000_cc_ent;
++		table_size = ARRAY_SIZE(netgear_r8000_cc_ent);
++	}
++
++	if (cc_ent && table_size) {
++		struct brcmfmac_pd_cc *cc;
++		size_t memsize;
++
++		memsize = table_size * sizeof(struct brcmfmac_pd_cc_entry);
++		cc = devm_kzalloc(dev, sizeof(*cc) + memsize, GFP_KERNEL);
++		if (!cc)
++			return;
++		cc->table_size = table_size;
++		memcpy(cc->table, cc_ent, memsize);
++		settings->country_codes = cc;
++	}
++}
++
+ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ 		    struct brcmf_mp_device *settings)
+ {
+@@ -43,6 +73,8 @@ void brcmf_of_probe(struct device *dev,
+ 		of_node_put(root);
+ 	}
+ 
++	brcmf_of_probe_cc(dev, settings);
++
+ 	if (!np || bus_type != BRCMF_BUSTYPE_SDIO ||
+ 	    !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
+ 		return;
diff --git a/package/kernel/mac80211/patches/brcm/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch b/package/kernel/mac80211/patches/brcm/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch
new file mode 100644
index 0000000..fe79c40
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch
@@ -0,0 +1,23 @@
+brcmfmac: do not use internal roaming engine by default
+
+Some evidence of curing disconnects with this disabled, so make it a default.
+Can be overridden with module parameter roamoff=0
+See: http://projectable.me/optimize-my-pi-wi-fi/
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+@@ -59,7 +59,11 @@ static int brcmf_fcmode;
+ module_param_named(fcmode, brcmf_fcmode, int, 0);
+ MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control");
+ 
++#if defined(CONFIG_ARCH_BCM2835)
++static int brcmf_roamoff = 1;
++#else
+ static int brcmf_roamoff;
++#endif
+ module_param_named(roamoff, brcmf_roamoff, int, 0400);
+ MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
+ 
diff --git a/package/kernel/mac80211/patches/brcm/998-survey.patch b/package/kernel/mac80211/patches/brcm/998-survey.patch
new file mode 100644
index 0000000..79a4578
--- /dev/null
+++ b/package/kernel/mac80211/patches/brcm/998-survey.patch
@@ -0,0 +1,148 @@
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -2916,6 +2916,63 @@ done:
+ }
+ 
+ static int
++brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
++			   int idx, struct survey_info *survey)
++{
++	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
++	struct brcmf_if *ifp = netdev_priv(ndev);
++	struct brcmu_chan ch;
++	enum nl80211_band band = 0;
++	s32 err = 0;
++	int noise;
++	u32 freq;
++	u32 chanspec;
++
++	memset(survey, 0, sizeof(struct survey_info));
++	if (idx != 0) {
++		if (idx >= cfg->pub->num_chan_stats || cfg->pub->chan_stats == NULL)
++			return -ENOENT;
++		if (cfg->pub->chan_stats[idx].freq == 0)
++			return -ENOENT;
++		survey->filled = SURVEY_INFO_NOISE_DBM;
++		survey->channel = ieee80211_get_channel(wiphy, cfg->pub->chan_stats[idx].freq);
++		survey->noise = cfg->pub->chan_stats[idx].noise;
++		return 0;
++	}
++
++	err = brcmf_fil_iovar_int_get(ifp, "chanspec", &chanspec);
++	if (err) {
++		brcmf_err("chanspec failed (%d)\n", err);
++		return err;
++	}
++
++	ch.chspec = chanspec;
++	cfg->d11inf.decchspec(&ch);
++
++	switch (ch.band) {
++	case BRCMU_CHAN_BAND_2G:
++		band = NL80211_BAND_2GHZ;
++		break;
++	case BRCMU_CHAN_BAND_5G:
++		band = NL80211_BAND_5GHZ;
++		break;
++	}
++
++	freq = ieee80211_channel_to_frequency(ch.control_ch_num, band);
++	survey->channel = ieee80211_get_channel(wiphy, freq);
++
++	err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PHY_NOISE, &noise);
++	if (err) {
++		brcmf_err("Could not get noise (%d)\n", err);
++		return err;
++	}
++
++	survey->filled = SURVEY_INFO_NOISE_DBM | SURVEY_INFO_IN_USE;
++	survey->noise = le32_to_cpu(noise);
++	return 0;
++}
++
++static int
+ brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
+ 			    int idx, u8 *mac, struct station_info *sinfo)
+ {
+@@ -3011,6 +3068,7 @@ static s32 brcmf_inform_single_bss(struc
+ 	struct brcmu_chan ch;
+ 	u16 channel;
+ 	u32 freq;
++	int i;
+ 	u16 notify_capability;
+ 	u16 notify_interval;
+ 	u8 *notify_ie;
+@@ -3035,6 +3093,17 @@ static s32 brcmf_inform_single_bss(struc
+ 		band = NL80211_BAND_5GHZ;
+ 
+ 	freq = ieee80211_channel_to_frequency(channel, band);
++	for (i = 0;i < cfg->pub->num_chan_stats;i++) {
++		if (freq == cfg->pub->chan_stats[i].freq)
++			break;
++		if (cfg->pub->chan_stats[i].freq == 0)
++			break;
++	}
++	if (i < cfg->pub->num_chan_stats) {
++		cfg->pub->chan_stats[i].freq = freq;
++		cfg->pub->chan_stats[i].noise = bi->phy_noise;
++	}
++
+ 	bss_data.chan = ieee80211_get_channel(wiphy, freq);
+ 	bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20;
+ 	bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime());
+@@ -5521,6 +5590,7 @@ static struct cfg80211_ops brcmf_cfg8021
+ 	.leave_ibss = brcmf_cfg80211_leave_ibss,
+ 	.get_station = brcmf_cfg80211_get_station,
+ 	.dump_station = brcmf_cfg80211_dump_station,
++	.dump_survey = brcmf_cfg80211_dump_survey,
+ 	.set_tx_power = brcmf_cfg80211_set_tx_power,
+ 	.get_tx_power = brcmf_cfg80211_get_tx_power,
+ 	.add_key = brcmf_cfg80211_add_key,
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1357,6 +1357,8 @@ int brcmf_attach(struct device *dev)
+ 
+ 	/* Link to bus module */
+ 	drvr->hdrlen = 0;
++	drvr->chan_stats = vzalloc(256 * sizeof(struct brcmf_chan_stats));
++	drvr->num_chan_stats = 256;
+ 
+ 	/* Attach and link in the protocol */
+ 	ret = brcmf_proto_attach(drvr);
+@@ -1439,6 +1441,12 @@ void brcmf_detach(struct device *dev)
+ 	if (drvr == NULL)
+ 		return;
+ 
++	drvr->num_chan_stats = 0;
++	if (drvr->chan_stats) {
++		vfree(drvr->chan_stats);
++		drvr->chan_stats = NULL;
++	}
++
+ #ifdef CONFIG_INET
+ 	unregister_inetaddr_notifier(&drvr->inetaddr_notifier);
+ #endif
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -91,6 +91,11 @@ struct brcmf_rev_info {
+ 	u32 nvramrev;
+ };
+ 
++struct brcmf_chan_stats {
++	u32 freq;
++	int noise;
++};
++
+ /* Common structure for module and instance linkage */
+ struct brcmf_pub {
+ 	/* Linkage ponters */
+@@ -100,6 +105,9 @@ struct brcmf_pub {
+ 	struct cfg80211_ops *ops;
+ 	struct brcmf_cfg80211_info *config;
+ 
++	int num_chan_stats;
++	struct brcmf_chan_stats *chan_stats;
++
+ 	/* Internal brcmf items */
+ 	uint hdrlen;		/* Total BRCMF header length (proto + bus) */
+