aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZoltan Herpai <wigyori@uid0.hu>2016-09-29 15:49:20 +0200
committerGitHub <noreply@github.com>2016-09-29 15:49:20 +0200
commitca3f1a614a1ee90fc67188b375888517f0c151df (patch)
tree930c456200793be1ec731e819aa0dd2e4b0b0dbf
parentd6b3ca24c50047af58135ad3090f7a3a25eee35d (diff)
parentf9755e28776fdce0c2136492b43380d0eefe3c5a (diff)
downloadupstream-ca3f1a614a1ee90fc67188b375888517f0c151df.tar.gz
upstream-ca3f1a614a1ee90fc67188b375888517f0c151df.tar.bz2
upstream-ca3f1a614a1ee90fc67188b375888517f0c151df.zip
Merge pull request #105 from wigyori/chaos_calmer
CC: openssl security upgrade, sync updates from git.openwrt.org/chaos_calmer
-rw-r--r--include/kernel-version.mk4
-rw-r--r--package/kernel/mac80211/patches/344-0001-brcmfmac-change-function-name-for-brcmf_cfg80211_wai.patch99
-rw-r--r--package/kernel/mac80211/patches/344-0002-brcmfmac-Limit-memory-allocs-to-64K.patch127
-rw-r--r--package/kernel/mac80211/patches/344-0003-brcmfmac-check-for-wowl-support-before-enumerating-f.patch29
-rw-r--r--package/kernel/mac80211/patches/344-0004-brcmfmac-Configure-country-code-using-device-specifi.patch214
-rw-r--r--package/kernel/mac80211/patches/344-0005-brcmfmac-Add-length-checks-on-firmware-events.patch283
-rw-r--r--package/kernel/mac80211/patches/344-0006-brcmfmac-add-neighbor-discovery-offload-ip-address-t.patch333
-rw-r--r--package/kernel/mac80211/patches/344-0007-brcmfmac-check-return-for-ARP-ip-setting-iovar.patch38
-rw-r--r--package/kernel/mac80211/patches/344-0011-brcmfmac-remove-pcie-gen1-support.patch221
-rw-r--r--package/kernel/mac80211/patches/344-0012-brcmfmac-increase-timeout-for-tx-eapol.patch2
-rw-r--r--package/kernel/mac80211/patches/344-0013-brcmfmac-move-module-init-and-exit-to-common.patch135
-rw-r--r--package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch260
-rw-r--r--package/kernel/mac80211/patches/344-0015-brcmfmac-move-platform-data-retrieval-code-to-common.patch385
-rw-r--r--package/kernel/mac80211/patches/344-0016-brcmfmac-keep-ARP-and-ND-offload-enabled-during-WOWL.patch69
-rw-r--r--package/kernel/mac80211/patches/344-0017-brcmfmac-switch-to-new-platform-data.patch734
-rw-r--r--package/kernel/mac80211/patches/344-0018-brcmfmac-merge-platform-data-and-module-paramaters.patch607
-rw-r--r--package/kernel/mac80211/patches/344-0019-brcmfmac-integrate-add_keyext-in-add_key.patch227
-rw-r--r--package/kernel/mac80211/patches/344-0020-brcmfmac-add-802.11w-management-frame-protection-sup.patch509
-rw-r--r--package/kernel/mac80211/patches/345-brcmfmac-Remove-waitqueue_active-check.patch54
-rw-r--r--package/kernel/mac80211/patches/346-brcmfmac-uninitialized-ret-variable.patch21
-rw-r--r--package/kernel/mac80211/patches/347-brcmfmac-sdio-remove-unused-variable-retry_limit.patch24
-rw-r--r--package/kernel/mac80211/patches/348-brcmfmac-Delete-unnecessary-variable-initialisation.patch26
-rw-r--r--package/kernel/mac80211/patches/349-0001-brcmfmac-clear-eventmask-array-before-using-it.patch27
-rw-r--r--package/kernel/mac80211/patches/349-0002-brcmfmac-fix-clearing-wowl-wake-indicators.patch27
-rw-r--r--package/kernel/mac80211/patches/349-0003-brcmfmac-insert-default-boardrev-in-nvram-data-if-mi.patch (renamed from package/kernel/mac80211/patches/345-brcmfmac-insert-default-boardrev-in-nvram-data-if-mi.patch)0
-rw-r--r--package/kernel/mac80211/patches/349-0004-brcmfmac-fix-p2p-scan-abort-null-pointer-exception.patch29
-rw-r--r--package/kernel/mac80211/patches/349-0005-brcmfmac-screening-firmware-event-packet.patch297
-rw-r--r--package/kernel/mac80211/patches/349-0006-brcmfmac-cleanup-ampdu-rx-host-reorder-code.patch585
-rw-r--r--package/kernel/mac80211/patches/349-0007-brcmfmac-revise-handling-events-in-receive-path.patch139
-rw-r--r--package/kernel/mac80211/patches/349-0008-brcmfmac-create-common-function-for-handling-brcmf_p.patch88
-rw-r--r--package/kernel/mac80211/patches/351-0005-brcmfmac-rework-function-picking-free-BSS-index.patch8
-rw-r--r--package/kernel/mac80211/patches/351-0007-brcmutil-add-field-storing-control-channel-to-the-st.patch20
-rw-r--r--package/kernel/mac80211/patches/351-0008-brcmfmac-support-get_channel-cfg80211-callback.patch4
-rw-r--r--package/kernel/mac80211/patches/351-0009-brcmfmac-print-errors-if-creating-interface-fails.patch4
-rw-r--r--package/kernel/mac80211/patches/351-0010-brcmfmac-fix-setting-AP-channel-with-new-firmwares.patch12
-rw-r--r--package/kernel/mac80211/patches/351-0011-brcmfmac-don-t-remove-interface-on-link-down-firmwar.patch4
-rw-r--r--package/kernel/mac80211/patches/351-0017-brcmfmac-drop-unused-pm_block-vif-attribute.patch103
-rw-r--r--package/kernel/mac80211/patches/351-0018-brcmfmac-include-required-headers-in-cfg80211.h.patch37
-rw-r--r--package/kernel/mac80211/patches/351-0019-brcmfmac-slightly-simplify-building-interface-combin.patch108
-rw-r--r--package/kernel/mac80211/patches/351-0020-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch160
-rw-r--r--package/kernel/mac80211/patches/351-0021-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch39
-rw-r--r--package/kernel/mac80211/patches/351-0022-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch33
-rw-r--r--package/kernel/mac80211/patches/351-0023-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch27
-rw-r--r--package/kernel/mac80211/patches/351-0024-brcmfmac-delete-interface-directly-in-code-that-sent.patch75
-rw-r--r--package/kernel/mac80211/patches/351-0025-brcmfmac-support-removing-AP-interfaces-with-interfa.patch84
-rw-r--r--package/kernel/mac80211/patches/351-0026-brcmfmac-respect-hidden_ssid-for-AP-interfaces.patch43
-rw-r--r--package/kernel/mac80211/patches/351-0027-brcmfmac-restore-stopping-netdev-queue-when-bus-clog.patch53
-rw-r--r--package/kernel/mac80211/patches/351-0028-brcmfmac-defer-DPC-processing-during-probe.patch42
-rw-r--r--package/kernel/mac80211/patches/351-0029-brcmfmac-Fix-glob_skb-leak-in-brcmf_sdiod_recv_chain.patch32
-rw-r--r--package/kernel/mac80211/patches/351-0030-net-wireless-broadcom-brcm80211-brcmfmac-usb-don-t-p.patch34
-rw-r--r--package/kernel/mac80211/patches/351-0031-brcmfmac-Check-rtnl_lock-is-locked-when-removing-int.patch111
-rw-r--r--package/kernel/mac80211/patches/351-0032-brcmfmac-Change-vif_event_lock-to-spinlock.patch175
-rw-r--r--package/kernel/mac80211/patches/351-0033-brcmfmac-add-missing-header-dependencies.patch29
-rw-r--r--package/kernel/mac80211/patches/351-0034-brcmfmac-Add-USB-ID-for-Cisco-Linksys-AE1200.patch51
-rw-r--r--package/kernel/mac80211/patches/351-0035-brcmfmac-fix-pmksa-bssid-usage.patch51
-rw-r--r--package/kernel/mac80211/patches/351-0036-brcmfmac-avoid-potential-stack-overflow-in-brcmf_cfg.patch34
-rw-r--r--package/kernel/mac80211/patches/351-0037-brcmfmac-add-support-for-bcm4339-chip-with-modalias-.patch55
-rw-r--r--package/kernel/mac80211/patches/351-0038-brcmfmac-sdio-shorten-retry-loop-in-brcmf_sdio_kso_c.patch56
-rw-r--r--package/kernel/mac80211/patches/351-0039-brcmfmac-ignore-11d-configuration-errors.patch84
-rw-r--r--package/kernel/mac80211/patches/351-0040-brcmfmac-rework-pointer-trickery-in-brcmf_proto_bcdc.patch32
-rw-r--r--package/kernel/mac80211/patches/351-0041-brcmfmac-fix-memory-leak-in-brcmf_flowring_add_tdls_.patch39
-rw-r--r--package/kernel/mac80211/patches/351-0042-brcmfmac-initialize-variable-in-brcmf_sdiod_regrl.patch28
-rw-r--r--package/kernel/mac80211/patches/351-0043-brcmfmac-remove-worker-from-.ndo_set_mac_address-cal.patch107
-rw-r--r--package/kernel/mac80211/patches/351-0044-brcmfmac-remove-unnecessary-null-pointer-check.patch31
-rw-r--r--package/kernel/mac80211/patches/351-0045-brcmfmac-fix-clearing-entry-IPv6-address.patch37
-rw-r--r--package/kernel/mac80211/patches/351-0046-brcmfmac-fix-out-of-bound-access-on-clearing-wowl-wa.patch44
-rw-r--r--package/kernel/mac80211/patches/351-0047-brcmfmac-simplify-mapping-of-auth-type.patch39
-rw-r--r--package/kernel/mac80211/patches/351-0048-brcmfmac-fix-memory-leak-in-brcmf_fill_bss_param.patch41
-rw-r--r--package/kernel/mac80211/patches/351-0049-brcmfmac-drop-unused-fields-from-struct-brcmf_pub.patch60
-rw-r--r--package/kernel/mac80211/patches/351-0050-brcmfmac-replace-WARNING-on-timeout-with-a-simple-er.patch38
-rw-r--r--package/kernel/mac80211/patches/351-0051-brcmfmac-use-correct-skb-freeing-helper-when-deletin.patch58
-rw-r--r--package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch26
-rw-r--r--package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch4
-rw-r--r--package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch2
-rw-r--r--package/kernel/mwlwifi/Makefile4
-rw-r--r--package/kernel/mwlwifi/patches/100-drop_old_api.patch92
-rw-r--r--package/kernel/mwlwifi/patches/110-api_sync.patch19
-rw-r--r--package/libs/openssl/Makefile4
-rw-r--r--package/system/rpcd/Makefile4
-rw-r--r--target/linux/ar71xx/patches-3.18/003-MIPS-ath79-make-bootconsole-wait-for-both-THRE-and-T.patch49
-rw-r--r--target/linux/ar71xx/patches-3.18/718-MIPS-ath79-add-EPG5000-support.patch6
-rw-r--r--target/linux/ar71xx/patches-3.18/736-MIPS-ath79-add-MC-MAC1200R-support.patch6
-rw-r--r--target/linux/ar71xx/patches-3.18/737-MIPS-ath79-add-om5p-an-support.patch4
-rw-r--r--target/linux/ar71xx/patches-3.18/738-MIPS-ath79-add-meraki-mr12-mr16-support.patch6
-rw-r--r--target/linux/ar71xx/patches-3.18/799-MIPS-ath79-add-minibox-v1-support.patch6
-rw-r--r--target/linux/ar71xx/patches-3.18/800-MIPS-ath79-add-RB922GS-support.patch6
-rw-r--r--target/linux/ar71xx/patches-3.18/902-unaligned_access_hacks.patch8
-rw-r--r--target/linux/ar71xx/patches-3.18/903-MIPS-ath79-ubnt-rocket-m-xw-support.patch2
-rw-r--r--target/linux/ar71xx/patches-3.18/904-MIPS-ath79-bitmain-antminer-s1-support.patch6
-rw-r--r--target/linux/ar71xx/patches-3.18/905-MIPS-ath79-bitmain-antminer-s3-support.patch6
-rw-r--r--target/linux/ar71xx/patches-3.18/906-MIPS-ath79-add-blackswift.patch6
-rw-r--r--target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-WPN824N.patch4
-rw-r--r--target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-tl-wa901nd-v4-support.patch40
-rw-r--r--target/linux/bcm53xx/patches-3.18/150-pci-do-not-probe-too-early.patch2
-rw-r--r--target/linux/bcm53xx/patches-3.18/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch2
-rw-r--r--target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch4
-rw-r--r--target/linux/brcm2708/patches-3.18/0054-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch2
-rw-r--r--target/linux/brcm2708/patches-3.18/0055-usb-core-make-overcurrent-messages-more-prominent.patch2
-rw-r--r--target/linux/brcm63xx/patches-3.18/803-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch2
-rw-r--r--target/linux/generic/patches-3.18/099-module_arch_freeing_init-new-hook-for-archs-before-m.patch10
-rw-r--r--target/linux/generic/patches-3.18/204-module_strip.patch4
-rw-r--r--target/linux/generic/patches-3.18/494-mtd-ubi-add-EOF-marker-support.patch2
-rw-r--r--target/linux/generic/patches-3.18/811-pci_disable_usb_common_quirks.patch2
-rw-r--r--target/linux/generic/patches-3.18/820-usb_add_usb_find_device_by_name.patch2
-rw-r--r--target/linux/lantiq/patches-3.18/0001-MIPS-lantiq-add-pcie-driver.patch2
-rw-r--r--target/linux/oxnas/patches-3.18/320-oxnas-irqchip.patch2
-rw-r--r--target/linux/ramips/patches-3.18/0037-USB-phy-add-ralink-SoC-driver.patch26
-rw-r--r--target/linux/ramips/patches-3.18/0052-i2c-MIPS-adds-ralink-I2C-driver.patch4
-rw-r--r--target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch9
-rw-r--r--target/linux/ramips/patches-3.18/0062-mt7621-add-ECHI-OCHI-XCHI-support.patch38
-rw-r--r--target/linux/sunxi/patches-3.18/116-dt-sunxi-update-compats-for-tempcurves.patch51
111 files changed, 7833 insertions, 358 deletions
diff --git a/include/kernel-version.mk b/include/kernel-version.mk
index f2744249d9..81cd12355e 100644
--- a/include/kernel-version.mk
+++ b/include/kernel-version.mk
@@ -2,9 +2,9 @@
LINUX_RELEASE?=1
-LINUX_VERSION-3.18 = .29
+LINUX_VERSION-3.18 = .36
-LINUX_KERNEL_MD5SUM-3.18.29 = b25737a0bc98e80d12200de93f239c28
+LINUX_KERNEL_MD5SUM-3.18.36 = 31b1699c1285aeeb81fb25750baa50d9
ifdef KERNEL_PATCHVER
LINUX_VERSION:=$(KERNEL_PATCHVER)$(strip $(LINUX_VERSION-$(KERNEL_PATCHVER)))
diff --git a/package/kernel/mac80211/patches/344-0001-brcmfmac-change-function-name-for-brcmf_cfg80211_wai.patch b/package/kernel/mac80211/patches/344-0001-brcmfmac-change-function-name-for-brcmf_cfg80211_wai.patch
new file mode 100644
index 0000000000..e3427de732
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0001-brcmfmac-change-function-name-for-brcmf_cfg80211_wai.patch
@@ -0,0 +1,99 @@
+From: Arend van Spriel <arend@broadcom.com>
+Date: Wed, 17 Feb 2016 11:26:50 +0100
+Subject: [PATCH] brcmfmac: change function name for
+ brcmf_cfg80211_wait_vif_event_timeout()
+
+Dropping the '_timeout' from the function name as the fact that a timeout
+value is passed makes it obvious a timeout is used. Also helps to keep code
+lines a bit shorter and easier to stick to 80 char boundary.
+
+Reviewed-by: Hante Meuleman <meuleman@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/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -564,8 +564,8 @@ struct wireless_dev *brcmf_ap_add_vif(st
+ }
+
+ /* wait for firmware event */
+- err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_ADD,
+- BRCMF_VIF_EVENT_TIMEOUT);
++ err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_ADD,
++ BRCMF_VIF_EVENT_TIMEOUT);
+ brcmf_cfg80211_arm_vif_event(cfg, NULL);
+ if (!err) {
+ brcmf_err("timeout occurred\n");
+@@ -6395,8 +6395,9 @@ bool brcmf_cfg80211_vif_event_armed(stru
+
+ return armed;
+ }
+-int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
+- u8 action, ulong timeout)
++
++int brcmf_cfg80211_wait_vif_event(struct brcmf_cfg80211_info *cfg,
++ u8 action, ulong timeout)
+ {
+ struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -402,8 +402,8 @@ bool brcmf_get_vif_state_any(struct brcm
+ void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
+ struct brcmf_cfg80211_vif *vif);
+ bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
+-int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
+- u8 action, ulong timeout);
++int brcmf_cfg80211_wait_vif_event(struct brcmf_cfg80211_info *cfg,
++ u8 action, ulong timeout);
+ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
+ struct brcmf_if *ifp, bool aborted,
+ bool fw_abort);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+@@ -1988,8 +1988,8 @@ int brcmf_p2p_ifchange(struct brcmf_cfg8
+ brcmf_cfg80211_arm_vif_event(cfg, NULL);
+ return err;
+ }
+- err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_CHANGE,
+- BRCMF_VIF_EVENT_TIMEOUT);
++ err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_CHANGE,
++ BRCMF_VIF_EVENT_TIMEOUT);
+ brcmf_cfg80211_arm_vif_event(cfg, NULL);
+ if (!err) {
+ brcmf_err("No BRCMF_E_IF_CHANGE event received\n");
+@@ -2090,8 +2090,8 @@ static struct wireless_dev *brcmf_p2p_cr
+ }
+
+ /* wait for firmware event */
+- err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD,
+- BRCMF_VIF_EVENT_TIMEOUT);
++ err = brcmf_cfg80211_wait_vif_event(p2p->cfg, BRCMF_E_IF_ADD,
++ BRCMF_VIF_EVENT_TIMEOUT);
+ brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
+ brcmf_fweh_p2pdev_setup(pri_ifp, false);
+ if (!err) {
+@@ -2180,8 +2180,8 @@ struct wireless_dev *brcmf_p2p_add_vif(s
+ }
+
+ /* wait for firmware event */
+- err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_ADD,
+- BRCMF_VIF_EVENT_TIMEOUT);
++ err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_ADD,
++ BRCMF_VIF_EVENT_TIMEOUT);
+ brcmf_cfg80211_arm_vif_event(cfg, NULL);
+ if (!err) {
+ brcmf_err("timeout occurred\n");
+@@ -2274,8 +2274,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+ }
+ if (!err) {
+ /* wait for firmware event */
+- err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL,
+- BRCMF_VIF_EVENT_TIMEOUT);
++ err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL,
++ BRCMF_VIF_EVENT_TIMEOUT);
+ if (!err)
+ err = -EIO;
+ else
diff --git a/package/kernel/mac80211/patches/344-0002-brcmfmac-Limit-memory-allocs-to-64K.patch b/package/kernel/mac80211/patches/344-0002-brcmfmac-Limit-memory-allocs-to-64K.patch
new file mode 100644
index 0000000000..9c336f774f
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0002-brcmfmac-Limit-memory-allocs-to-64K.patch
@@ -0,0 +1,127 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:26:51 +0100
+Subject: [PATCH] brcmfmac: Limit memory allocs to <64K
+
+Some systems have problems with allocating memory allocation larger
+then 64K. Often on unload/load or suspend/resume a failure is
+reported: Could not allocate wiphy device. This patch makes the
+escan intermediate storage buf dynamically allocated, and smaller
+than 64K.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -1125,7 +1125,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
+
+ /* Arm scan timeout timer */
+ mod_timer(&cfg->escan_timeout, jiffies +
+- WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
++ BRCMF_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
+
+ return 0;
+
+@@ -3020,7 +3020,7 @@ brcmf_cfg80211_escan_handler(struct brcm
+
+ list = (struct brcmf_scan_results *)
+ cfg->escan_info.escan_buf;
+- if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) {
++ if (bi_length > BRCMF_ESCAN_BUF_SIZE - list->buflen) {
+ brcmf_err("Buffer is too small: ignoring\n");
+ goto exit;
+ }
+@@ -3033,8 +3033,8 @@ brcmf_cfg80211_escan_handler(struct brcm
+ bss_info_le))
+ goto exit;
+ }
+- memcpy(&(cfg->escan_info.escan_buf[list->buflen]),
+- bss_info_le, bi_length);
++ memcpy(&cfg->escan_info.escan_buf[list->buflen], bss_info_le,
++ bi_length);
+ list->version = le32_to_cpu(bss_info_le->version);
+ list->buflen += bi_length;
+ list->count++;
+@@ -5402,14 +5402,14 @@ static void brcmf_deinit_priv_mem(struct
+ {
+ kfree(cfg->conf);
+ cfg->conf = NULL;
+- kfree(cfg->escan_ioctl_buf);
+- cfg->escan_ioctl_buf = NULL;
+ kfree(cfg->extra_buf);
+ cfg->extra_buf = NULL;
+ kfree(cfg->wowl.nd);
+ cfg->wowl.nd = NULL;
+ kfree(cfg->wowl.nd_info);
+ cfg->wowl.nd_info = NULL;
++ kfree(cfg->escan_info.escan_buf);
++ cfg->escan_info.escan_buf = NULL;
+ }
+
+ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
+@@ -5417,9 +5417,6 @@ static s32 brcmf_init_priv_mem(struct br
+ cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
+ if (!cfg->conf)
+ goto init_priv_mem_out;
+- cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
+- if (!cfg->escan_ioctl_buf)
+- goto init_priv_mem_out;
+ cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+ if (!cfg->extra_buf)
+ goto init_priv_mem_out;
+@@ -5431,6 +5428,9 @@ static s32 brcmf_init_priv_mem(struct br
+ GFP_KERNEL);
+ if (!cfg->wowl.nd_info)
+ goto init_priv_mem_out;
++ cfg->escan_info.escan_buf = kzalloc(BRCMF_ESCAN_BUF_SIZE, GFP_KERNEL);
++ if (!cfg->escan_info.escan_buf)
++ goto init_priv_mem_out;
+
+ return 0;
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -28,8 +28,11 @@
+ #define WL_ROAM_TRIGGER_LEVEL -75
+ #define WL_ROAM_DELTA 20
+
+-#define WL_ESCAN_BUF_SIZE (1024 * 64)
+-#define WL_ESCAN_TIMER_INTERVAL_MS 10000 /* E-Scan timeout */
++/* Keep BRCMF_ESCAN_BUF_SIZE below 64K (65536). Allocing over 64K can be
++ * problematic on some systems and should be avoided.
++ */
++#define BRCMF_ESCAN_BUF_SIZE 65000
++#define BRCMF_ESCAN_TIMER_INTERVAL_MS 10000 /* E-Scan timeout */
+
+ #define WL_ESCAN_ACTION_START 1
+ #define WL_ESCAN_ACTION_CONTINUE 2
+@@ -205,7 +208,7 @@ enum wl_escan_state {
+
+ struct escan_info {
+ u32 escan_state;
+- u8 escan_buf[WL_ESCAN_BUF_SIZE];
++ u8 *escan_buf;
+ struct wiphy *wiphy;
+ struct brcmf_if *ifp;
+ s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
+@@ -278,7 +281,6 @@ struct brcmf_cfg80211_wowl {
+ * @escan_info: escan information.
+ * @escan_timeout: Timer for catch scan timeout.
+ * @escan_timeout_work: scan timeout worker.
+- * @escan_ioctl_buf: dongle command buffer for escan commands.
+ * @vif_list: linked list of vif instances.
+ * @vif_cnt: number of vif instances.
+ * @vif_event: vif event signalling.
+@@ -309,7 +311,6 @@ struct brcmf_cfg80211_info {
+ struct escan_info escan_info;
+ struct timer_list escan_timeout;
+ struct work_struct escan_timeout_work;
+- u8 *escan_ioctl_buf;
+ struct list_head vif_list;
+ struct brcmf_cfg80211_vif_event vif_event;
+ struct completion vif_disabled;
diff --git a/package/kernel/mac80211/patches/344-0003-brcmfmac-check-for-wowl-support-before-enumerating-f.patch b/package/kernel/mac80211/patches/344-0003-brcmfmac-check-for-wowl-support-before-enumerating-f.patch
new file mode 100644
index 0000000000..ee3d9f37a8
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0003-brcmfmac-check-for-wowl-support-before-enumerating-f.patch
@@ -0,0 +1,29 @@
+From: Franky Lin <frankyl@broadcom.com>
+Date: Wed, 17 Feb 2016 11:26:52 +0100
+Subject: [PATCH] brcmfmac: check for wowl support before enumerating feature
+ flag
+
+In some cases wiphy->wowlan could be NULL if firmware doesn't have the
+support. Driver should check for support before walking down the feature
+flags.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+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/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -6594,7 +6594,8 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_RANDOM_MAC)) {
+ wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
+ #ifdef CONFIG_PM
+- if (wiphy->wowlan->flags & WIPHY_WOWLAN_NET_DETECT)
++ if (wiphy->wowlan &&
++ wiphy->wowlan->flags & WIPHY_WOWLAN_NET_DETECT)
+ wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
+ #endif
+ }
diff --git a/package/kernel/mac80211/patches/344-0004-brcmfmac-Configure-country-code-using-device-specifi.patch b/package/kernel/mac80211/patches/344-0004-brcmfmac-Configure-country-code-using-device-specifi.patch
new file mode 100644
index 0000000000..c52cac87b9
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0004-brcmfmac-Configure-country-code-using-device-specifi.patch
@@ -0,0 +1,214 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:26:53 +0100
+Subject: [PATCH] brcmfmac: Configure country code using device specific
+ settings
+
+Country code configuration in a device is a device specific
+operation. For this the country code as specified by reg notifier
+(iso3166 alpha2) needs to be translated to a device specific
+country locale and revision number. This patch adds this
+translation and puts a placeholder in the device specific settings
+where the translation table can be stored. Additional patches will
+be needed to read these tables from for example device platform
+data.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -6405,28 +6405,85 @@ int brcmf_cfg80211_wait_vif_event(struct
+ vif_event_equals(event, action), timeout);
+ }
+
++static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2],
++ struct brcmf_fil_country_le *ccreq)
++{
++ struct cc_translate *country_codes;
++ struct cc_entry *cc;
++ s32 found_index;
++ int i;
++
++ country_codes = drvr->settings->country_codes;
++ if (!country_codes) {
++ brcmf_dbg(TRACE, "No country codes configured for device\n");
++ return -EINVAL;
++ }
++
++ if ((alpha2[0] == ccreq->country_abbrev[0]) &&
++ (alpha2[1] == ccreq->country_abbrev[1])) {
++ brcmf_dbg(TRACE, "Country code already set\n");
++ return -EAGAIN;
++ }
++
++ found_index = -1;
++ for (i = 0; i < country_codes->table_size; i++) {
++ cc = &country_codes->table[i];
++ if ((cc->iso3166[0] == '\0') && (found_index == -1))
++ found_index = i;
++ if ((cc->iso3166[0] == alpha2[0]) &&
++ (cc->iso3166[1] == alpha2[1])) {
++ found_index = i;
++ break;
++ }
++ }
++ if (found_index == -1) {
++ brcmf_dbg(TRACE, "No country code match found\n");
++ return -EINVAL;
++ }
++ memset(ccreq, 0, sizeof(*ccreq));
++ ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev);
++ memcpy(ccreq->ccode, country_codes->table[found_index].cc,
++ BRCMF_COUNTRY_BUF_SZ);
++ ccreq->country_abbrev[0] = alpha2[0];
++ ccreq->country_abbrev[1] = alpha2[1];
++ ccreq->country_abbrev[2] = 0;
++
++ return 0;
++}
++
+ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
+ struct regulatory_request *req)
+ {
+ struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
+ struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+ struct brcmf_fil_country_le ccreq;
++ s32 err;
+ int i;
+
+- brcmf_dbg(TRACE, "enter: initiator=%d, alpha=%c%c\n", req->initiator,
+- req->alpha2[0], req->alpha2[1]);
+-
+ /* ignore non-ISO3166 country codes */
+ for (i = 0; i < sizeof(req->alpha2); i++)
+ if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
+- brcmf_err("not a ISO3166 code\n");
++ brcmf_err("not a ISO3166 code (0x%02x 0x%02x)\n",
++ req->alpha2[0], req->alpha2[1]);
+ return;
+ }
+- memset(&ccreq, 0, sizeof(ccreq));
+- ccreq.rev = cpu_to_le32(-1);
+- memcpy(ccreq.ccode, req->alpha2, sizeof(req->alpha2));
+- if (brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq))) {
+- brcmf_err("firmware rejected country setting\n");
++
++ brcmf_dbg(TRACE, "Enter: initiator=%d, alpha=%c%c\n", req->initiator,
++ req->alpha2[0], req->alpha2[1]);
++
++ err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq));
++ if (err) {
++ brcmf_err("Country code iovar returned err = %d\n", err);
++ return;
++ }
++
++ err = brcmf_translate_country_code(ifp->drvr, req->alpha2, &ccreq);
++ if (err)
++ return;
++
++ err = brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq));
++ if (err) {
++ brcmf_err("Firmware rejected country setting\n");
+ return;
+ }
+ brcmf_setup_wiphybands(wiphy);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+@@ -230,10 +230,8 @@ void brcmf_mp_attach(void)
+ int brcmf_mp_device_attach(struct brcmf_pub *drvr)
+ {
+ drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC);
+- if (!drvr->settings) {
+- brcmf_err("Failed to alloca storage space for settings\n");
++ if (!drvr->settings)
+ return -ENOMEM;
+- }
+
+ drvr->settings->sdiod_txglomsz = brcmf_sdiod_txglomsz;
+ drvr->settings->p2p_enable = !!brcmf_p2p_enable;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+@@ -15,6 +15,8 @@
+ #ifndef BRCMFMAC_COMMON_H
+ #define BRCMFMAC_COMMON_H
+
++#include "fwil_types.h"
++
+ extern const u8 ALLFFMAC[ETH_ALEN];
+
+ #define BRCMF_FW_ALTPATH_LEN 256
+@@ -39,6 +41,33 @@ struct brcmf_mp_global_t {
+ extern struct brcmf_mp_global_t brcmf_mp_global;
+
+ /**
++ * struct cc_entry - Struct for translating user space country code (iso3166) to
++ * firmware country code and revision.
++ *
++ * @iso3166: iso3166 alpha 2 country code string.
++ * @cc: firmware country code string.
++ * @rev: firmware country code revision.
++ */
++struct cc_entry {
++ char iso3166[BRCMF_COUNTRY_BUF_SZ];
++ char cc[BRCMF_COUNTRY_BUF_SZ];
++ s32 rev;
++};
++
++/**
++ * struct cc_translate - Struct for translating country codes as set by user
++ * space to a country code and rev which can be used by
++ * firmware.
++ *
++ * @table_size: number of entries in table (> 0)
++ * @table: dynamic array of 1 or more elements with translation information.
++ */
++struct cc_translate {
++ int table_size;
++ struct cc_entry table[0];
++};
++
++/**
+ * struct brcmf_mp_device - Device module paramaters.
+ *
+ * @sdiod_txglomsz: SDIO txglom size.
+@@ -47,6 +76,7 @@ extern struct brcmf_mp_global_t brcmf_mp
+ * @feature_disable: Feature_disable bitmask.
+ * @fcmode: FWS flow control.
+ * @roamoff: Firmware roaming off?
++ * @country_codes: If available, pointer to struct for translating country codes
+ */
+ struct brcmf_mp_device {
+ int sdiod_txglomsz;
+@@ -56,6 +86,7 @@ struct brcmf_mp_device {
+ int fcmode;
+ bool roamoff;
+ bool ignore_probe_fail;
++ struct cc_translate *country_codes;
+ };
+
+ void brcmf_mp_attach(void);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+@@ -134,6 +134,8 @@
+ #define BRCMF_PFN_MAC_OUI_ONLY BIT(0)
+ #define BRCMF_PFN_SET_MAC_UNASSOC BIT(1)
+
++#define BRCMF_MCSSET_LEN 16
++
+ /* join preference types for join_pref iovar */
+ enum brcmf_join_pref_types {
+ BRCMF_JOIN_PREF_RSSI = 1,
+@@ -279,7 +281,7 @@ struct brcmf_bss_info_le {
+ __le32 reserved32[1]; /* Reserved for expansion of BSS properties */
+ u8 flags; /* flags */
+ u8 reserved[3]; /* Reserved for expansion of BSS properties */
+- u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
++ u8 basic_mcs[BRCMF_MCSSET_LEN]; /* 802.11N BSS required MCS set */
+
+ __le16 ie_offset; /* offset at which IEs start, from beginning */
+ __le32 ie_length; /* byte length of Information Elements */
diff --git a/package/kernel/mac80211/patches/344-0005-brcmfmac-Add-length-checks-on-firmware-events.patch b/package/kernel/mac80211/patches/344-0005-brcmfmac-Add-length-checks-on-firmware-events.patch
new file mode 100644
index 0000000000..3e2e3503b6
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0005-brcmfmac-Add-length-checks-on-firmware-events.patch
@@ -0,0 +1,283 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:26:54 +0100
+Subject: [PATCH] brcmfmac: Add length checks on firmware events
+
+Add additional length checks on firmware events to create more
+robust code.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Reviewed-by: Lei Zhang <leizh@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -3092,6 +3092,11 @@ brcmf_notify_sched_scan_results(struct b
+
+ brcmf_dbg(SCAN, "Enter\n");
+
++ if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
++ brcmf_dbg(SCAN, "Event data to small. Ignore\n");
++ return 0;
++ }
++
+ if (e->event_code == BRCMF_E_PFN_NET_LOST) {
+ brcmf_dbg(SCAN, "PFN NET LOST event. Do Nothing\n");
+ return 0;
+@@ -3415,6 +3420,11 @@ brcmf_wowl_nd_results(struct brcmf_if *i
+
+ brcmf_dbg(SCAN, "Enter\n");
+
++ if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
++ brcmf_dbg(SCAN, "Event data to small. Ignore\n");
++ return 0;
++ }
++
+ pfn_result = (struct brcmf_pno_scanresults_le *)data;
+
+ if (e->event_code == BRCMF_E_PFN_NET_LOST) {
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+@@ -26,50 +26,6 @@
+ #include "fwil.h"
+
+ /**
+- * struct brcm_ethhdr - broadcom specific ether header.
+- *
+- * @subtype: subtype for this packet.
+- * @length: TODO: length of appended data.
+- * @version: version indication.
+- * @oui: OUI of this packet.
+- * @usr_subtype: subtype for this OUI.
+- */
+-struct brcm_ethhdr {
+- __be16 subtype;
+- __be16 length;
+- u8 version;
+- u8 oui[3];
+- __be16 usr_subtype;
+-} __packed;
+-
+-struct brcmf_event_msg_be {
+- __be16 version;
+- __be16 flags;
+- __be32 event_type;
+- __be32 status;
+- __be32 reason;
+- __be32 auth_type;
+- __be32 datalen;
+- u8 addr[ETH_ALEN];
+- char ifname[IFNAMSIZ];
+- u8 ifidx;
+- u8 bsscfgidx;
+-} __packed;
+-
+-/**
+- * struct brcmf_event - contents of broadcom event packet.
+- *
+- * @eth: standard ether header.
+- * @hdr: broadcom specific ether header.
+- * @msg: common part of the actual event message.
+- */
+-struct brcmf_event {
+- struct ethhdr eth;
+- struct brcm_ethhdr hdr;
+- struct brcmf_event_msg_be msg;
+-} __packed;
+-
+-/**
+ * struct brcmf_fweh_queue_item - event item on event queue.
+ *
+ * @q: list element for queuing.
+@@ -85,6 +41,7 @@ struct brcmf_fweh_queue_item {
+ u8 ifidx;
+ u8 ifaddr[ETH_ALEN];
+ struct brcmf_event_msg_be emsg;
++ u32 datalen;
+ u8 data[0];
+ };
+
+@@ -294,6 +251,11 @@ static void brcmf_fweh_event_worker(stru
+ brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data,
+ min_t(u32, emsg.datalen, 64),
+ "event payload, len=%d\n", emsg.datalen);
++ if (emsg.datalen > event->datalen) {
++ brcmf_err("event invalid length header=%d, msg=%d\n",
++ event->datalen, emsg.datalen);
++ goto event_free;
++ }
+
+ /* special handling of interface event */
+ if (event->code == BRCMF_E_IF) {
+@@ -439,7 +401,8 @@ int brcmf_fweh_activate_events(struct br
+ * dispatch the event to a registered handler (using worker).
+ */
+ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
+- struct brcmf_event *event_packet)
++ struct brcmf_event *event_packet,
++ u32 packet_len)
+ {
+ enum brcmf_fweh_event_code code;
+ struct brcmf_fweh_info *fweh = &drvr->fweh;
+@@ -459,6 +422,9 @@ void brcmf_fweh_process_event(struct brc
+ if (code != BRCMF_E_IF && !fweh->evt_handler[code])
+ return;
+
++ if (datalen > BRCMF_DCMD_MAXLEN)
++ return;
++
+ if (in_interrupt())
+ alloc_flag = GFP_ATOMIC;
+
+@@ -472,6 +438,7 @@ void brcmf_fweh_process_event(struct brc
+ /* use memcpy to get aligned event message */
+ memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
+ memcpy(event->data, data, datalen);
++ event->datalen = datalen;
+ memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN);
+
+ brcmf_fweh_queue_event(fweh, event);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+@@ -27,7 +27,6 @@
+ struct brcmf_pub;
+ struct brcmf_if;
+ struct brcmf_cfg80211_info;
+-struct brcmf_event;
+
+ /* list of firmware events */
+ #define BRCMF_FWEH_EVENT_ENUM_DEFLIST \
+@@ -180,13 +179,55 @@ enum brcmf_fweh_event_code {
+ /**
+ * definitions for event packet validation.
+ */
+-#define BRCMF_EVENT_OUI_OFFSET 19
+-#define BRCM_OUI "\x00\x10\x18"
+-#define DOT11_OUI_LEN 3
+-#define BCMILCP_BCM_SUBTYPE_EVENT 1
++#define BRCM_OUI "\x00\x10\x18"
++#define BCMILCP_BCM_SUBTYPE_EVENT 1
+
+
+ /**
++ * struct brcm_ethhdr - broadcom specific ether header.
++ *
++ * @subtype: subtype for this packet.
++ * @length: TODO: length of appended data.
++ * @version: version indication.
++ * @oui: OUI of this packet.
++ * @usr_subtype: subtype for this OUI.
++ */
++struct brcm_ethhdr {
++ __be16 subtype;
++ __be16 length;
++ u8 version;
++ u8 oui[3];
++ __be16 usr_subtype;
++} __packed;
++
++struct brcmf_event_msg_be {
++ __be16 version;
++ __be16 flags;
++ __be32 event_type;
++ __be32 status;
++ __be32 reason;
++ __be32 auth_type;
++ __be32 datalen;
++ u8 addr[ETH_ALEN];
++ char ifname[IFNAMSIZ];
++ u8 ifidx;
++ u8 bsscfgidx;
++} __packed;
++
++/**
++ * struct brcmf_event - contents of broadcom event packet.
++ *
++ * @eth: standard ether header.
++ * @hdr: broadcom specific ether header.
++ * @msg: common part of the actual event message.
++ */
++struct brcmf_event {
++ struct ethhdr eth;
++ struct brcm_ethhdr hdr;
++ struct brcmf_event_msg_be msg;
++} __packed;
++
++/**
+ * struct brcmf_event_msg - firmware event message.
+ *
+ * @version: version information.
+@@ -256,34 +297,35 @@ void brcmf_fweh_unregister(struct brcmf_
+ enum brcmf_fweh_event_code code);
+ int brcmf_fweh_activate_events(struct brcmf_if *ifp);
+ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
+- struct brcmf_event *event_packet);
++ struct brcmf_event *event_packet,
++ u32 packet_len);
+ void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing);
+
+ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
+ struct sk_buff *skb)
+ {
+ struct brcmf_event *event_packet;
+- u8 *data;
+ u16 usr_stype;
+
+ /* only process events when protocol matches */
+ if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
+ return;
+
++ if ((skb->len + ETH_HLEN) < sizeof(*event_packet))
++ return;
++
+ /* check for BRCM oui match */
+ event_packet = (struct brcmf_event *)skb_mac_header(skb);
+- data = (u8 *)event_packet;
+- data += BRCMF_EVENT_OUI_OFFSET;
+- if (memcmp(BRCM_OUI, data, DOT11_OUI_LEN))
++ if (memcmp(BRCM_OUI, &event_packet->hdr.oui[0],
++ sizeof(event_packet->hdr.oui)))
+ return;
+
+ /* final match on usr_subtype */
+- data += DOT11_OUI_LEN;
+- usr_stype = get_unaligned_be16(data);
++ usr_stype = get_unaligned_be16(&event_packet->hdr.usr_subtype);
+ if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
+ return;
+
+- brcmf_fweh_process_event(drvr, event_packet);
++ brcmf_fweh_process_event(drvr, event_packet, skb->len + ETH_HLEN);
+ }
+
+ #endif /* FWEH_H_ */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+@@ -1361,6 +1361,11 @@ int brcmf_p2p_notify_action_frame_rx(str
+ u16 mgmt_type;
+ u8 action;
+
++ if (e->datalen < sizeof(*rxframe)) {
++ brcmf_dbg(SCAN, "Event data to small. Ignore\n");
++ return 0;
++ }
++
+ ch.chspec = be16_to_cpu(rxframe->chanspec);
+ cfg->d11inf.decchspec(&ch);
+ /* Check if wpa_supplicant has registered for this frame */
+@@ -1858,6 +1863,11 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probere
+ brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code,
+ e->reason);
+
++ if (e->datalen < sizeof(*rxframe)) {
++ brcmf_dbg(SCAN, "Event data to small. Ignore\n");
++ return 0;
++ }
++
+ ch.chspec = be16_to_cpu(rxframe->chanspec);
+ cfg->d11inf.decchspec(&ch);
+
diff --git a/package/kernel/mac80211/patches/344-0006-brcmfmac-add-neighbor-discovery-offload-ip-address-t.patch b/package/kernel/mac80211/patches/344-0006-brcmfmac-add-neighbor-discovery-offload-ip-address-t.patch
new file mode 100644
index 0000000000..888ad5b050
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0006-brcmfmac-add-neighbor-discovery-offload-ip-address-t.patch
@@ -0,0 +1,333 @@
+From: Franky Lin <frankyl@broadcom.com>
+Date: Wed, 17 Feb 2016 11:26:55 +0100
+Subject: [PATCH] brcmfmac: add neighbor discovery offload ip address table
+ configuration
+
+Configure ipv6 address for neighbor discovery offload ip table in
+firmware obtained through ipv6 address notification callback.
+
+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/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -456,7 +456,7 @@ send_key_to_dongle(struct brcmf_if *ifp,
+ }
+
+ static s32
+-brcmf_configure_arp_offload(struct brcmf_if *ifp, bool enable)
++brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
+ {
+ s32 err;
+ u32 mode;
+@@ -484,6 +484,15 @@ brcmf_configure_arp_offload(struct brcmf
+ enable, mode);
+ }
+
++ err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable);
++ if (err) {
++ brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n",
++ enable, err);
++ err = 0;
++ } else
++ brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n",
++ enable, mode);
++
+ return err;
+ }
+
+@@ -3543,7 +3552,7 @@ static s32 brcmf_cfg80211_resume(struct
+ brcmf_report_wowl_wakeind(wiphy, ifp);
+ brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
+ brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
+- brcmf_configure_arp_offload(ifp, true);
++ brcmf_configure_arp_nd_offload(ifp, true);
+ brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,
+ cfg->wowl.pre_pmmode);
+ cfg->wowl.active = false;
+@@ -3567,7 +3576,7 @@ static void brcmf_configure_wowl(struct
+
+ brcmf_dbg(TRACE, "Suspend, wowl config.\n");
+
+- brcmf_configure_arp_offload(ifp, false);
++ brcmf_configure_arp_nd_offload(ifp, false);
+ brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->wowl.pre_pmmode);
+ brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX);
+
+@@ -4336,7 +4345,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+
+ if (!mbss) {
+ brcmf_set_mpc(ifp, 0);
+- brcmf_configure_arp_offload(ifp, false);
++ brcmf_configure_arp_nd_offload(ifp, false);
+ }
+
+ /* find the RSN_IE */
+@@ -4482,7 +4491,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+ exit:
+ if ((err) && (!mbss)) {
+ brcmf_set_mpc(ifp, 1);
+- brcmf_configure_arp_offload(ifp, true);
++ brcmf_configure_arp_nd_offload(ifp, true);
+ }
+ return err;
+ }
+@@ -4540,7 +4549,7 @@ static int brcmf_cfg80211_stop_ap(struct
+ brcmf_err("bss_enable config failed %d\n", err);
+ }
+ brcmf_set_mpc(ifp, 1);
+- brcmf_configure_arp_offload(ifp, true);
++ brcmf_configure_arp_nd_offload(ifp, true);
+ clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
+ brcmf_net_setcarrier(ifp, false);
+
+@@ -6287,7 +6296,7 @@ static s32 brcmf_config_dongle(struct br
+ if (err)
+ goto default_conf_out;
+
+- brcmf_configure_arp_offload(ifp, true);
++ brcmf_configure_arp_nd_offload(ifp, true);
+
+ cfg->dongle_up = true;
+ default_conf_out:
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -20,6 +20,8 @@
+ #include <linux/inetdevice.h>
+ #include <net/cfg80211.h>
+ #include <net/rtnetlink.h>
++#include <net/addrconf.h>
++#include <net/ipv6.h>
+ #include <brcmu_utils.h>
+ #include <brcmu_wifi.h>
+
+@@ -172,6 +174,35 @@ _brcmf_set_mac_address(struct work_struc
+ }
+ }
+
++#if IS_ENABLED(CONFIG_IPV6)
++static void _brcmf_update_ndtable(struct work_struct *work)
++{
++ struct brcmf_if *ifp;
++ int i, ret;
++
++ ifp = container_of(work, struct brcmf_if, ndoffload_work);
++
++ /* clear the table in firmware */
++ ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip_clear", NULL, 0);
++ if (ret) {
++ brcmf_dbg(TRACE, "fail to clear nd ip table err:%d\n", ret);
++ return;
++ }
++
++ for (i = 0; i < ifp->ipv6addr_idx; i++) {
++ ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip",
++ &ifp->ipv6_addr_tbl[i],
++ sizeof(struct in6_addr));
++ if (ret)
++ brcmf_err("add nd ip err %d\n", ret);
++ }
++}
++#else
++static void _brcmf_update_ndtable(struct work_struct *work)
++{
++}
++#endif
++
+ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
+ {
+ struct brcmf_if *ifp = netdev_priv(ndev);
+@@ -685,6 +716,7 @@ int brcmf_net_attach(struct brcmf_if *if
+
+ INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
+ INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
++ INIT_WORK(&ifp->ndoffload_work, _brcmf_update_ndtable);
+
+ if (rtnl_locked)
+ err = register_netdevice(ndev);
+@@ -884,6 +916,7 @@ static void brcmf_del_if(struct brcmf_pu
+ if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+ cancel_work_sync(&ifp->setmacaddr_work);
+ cancel_work_sync(&ifp->multicast_work);
++ cancel_work_sync(&ifp->ndoffload_work);
+ }
+ brcmf_net_detach(ifp->ndev);
+ } else {
+@@ -1025,6 +1058,56 @@ static int brcmf_inetaddr_changed(struct
+ }
+ #endif
+
++#if IS_ENABLED(CONFIG_IPV6)
++static int brcmf_inet6addr_changed(struct notifier_block *nb,
++ unsigned long action, void *data)
++{
++ struct brcmf_pub *drvr = container_of(nb, struct brcmf_pub,
++ inet6addr_notifier);
++ struct inet6_ifaddr *ifa = data;
++ struct brcmf_if *ifp;
++ int i;
++ struct in6_addr *table;
++
++ /* Only handle primary interface */
++ ifp = drvr->iflist[0];
++ if (!ifp)
++ return NOTIFY_DONE;
++ if (ifp->ndev != ifa->idev->dev)
++ return NOTIFY_DONE;
++
++ table = ifp->ipv6_addr_tbl;
++ for (i = 0; i < NDOL_MAX_ENTRIES; i++)
++ if (ipv6_addr_equal(&ifa->addr, &table[i]))
++ break;
++
++ switch (action) {
++ case NETDEV_UP:
++ if (i == NDOL_MAX_ENTRIES) {
++ if (ifp->ipv6addr_idx < NDOL_MAX_ENTRIES) {
++ table[ifp->ipv6addr_idx++] = ifa->addr;
++ } else {
++ for (i = 0; i < NDOL_MAX_ENTRIES - 1; i++)
++ table[i] = table[i + 1];
++ table[NDOL_MAX_ENTRIES - 1] = ifa->addr;
++ }
++ }
++ break;
++ case NETDEV_DOWN:
++ if (i < NDOL_MAX_ENTRIES)
++ for (; i < ifp->ipv6addr_idx; i++)
++ table[i] = table[i + 1];
++ break;
++ default:
++ break;
++ }
++
++ schedule_work(&ifp->ndoffload_work);
++
++ return NOTIFY_OK;
++}
++#endif
++
+ int brcmf_attach(struct device *dev)
+ {
+ struct brcmf_pub *drvr = NULL;
+@@ -1164,30 +1247,41 @@ int brcmf_bus_start(struct device *dev)
+ #ifdef CONFIG_INET
+ drvr->inetaddr_notifier.notifier_call = brcmf_inetaddr_changed;
+ ret = register_inetaddr_notifier(&drvr->inetaddr_notifier);
++ if (ret)
++ goto fail;
++
++#if IS_ENABLED(CONFIG_IPV6)
++ drvr->inet6addr_notifier.notifier_call = brcmf_inet6addr_changed;
++ ret = register_inet6addr_notifier(&drvr->inet6addr_notifier);
++ if (ret) {
++ unregister_inetaddr_notifier(&drvr->inetaddr_notifier);
++ goto fail;
++ }
+ #endif
++#endif /* CONFIG_INET */
++
++ return 0;
+
+ fail:
+- if (ret < 0) {
+- brcmf_err("failed: %d\n", ret);
+- if (drvr->config) {
+- brcmf_cfg80211_detach(drvr->config);
+- drvr->config = NULL;
+- }
+- if (drvr->fws) {
+- brcmf_fws_del_interface(ifp);
+- brcmf_fws_deinit(drvr);
+- }
+- if (ifp)
+- brcmf_net_detach(ifp->ndev);
+- if (p2p_ifp)
+- brcmf_net_detach(p2p_ifp->ndev);
+- drvr->iflist[0] = NULL;
+- drvr->iflist[1] = NULL;
+- if (brcmf_ignoring_probe_fail(drvr))
+- ret = 0;
+- return ret;
++ brcmf_err("failed: %d\n", ret);
++ if (drvr->config) {
++ brcmf_cfg80211_detach(drvr->config);
++ drvr->config = NULL;
++ }
++ if (drvr->fws) {
++ brcmf_fws_del_interface(ifp);
++ brcmf_fws_deinit(drvr);
+ }
+- return 0;
++ if (ifp)
++ brcmf_net_detach(ifp->ndev);
++ if (p2p_ifp)
++ brcmf_net_detach(p2p_ifp->ndev);
++ drvr->iflist[0] = NULL;
++ drvr->iflist[1] = NULL;
++ if (brcmf_ignoring_probe_fail(drvr))
++ ret = 0;
++
++ return ret;
+ }
+
+ void brcmf_bus_add_txhdrlen(struct device *dev, uint len)
+@@ -1237,6 +1331,10 @@ void brcmf_detach(struct device *dev)
+ unregister_inetaddr_notifier(&drvr->inetaddr_notifier);
+ #endif
+
++#if IS_ENABLED(CONFIG_IPV6)
++ unregister_inet6addr_notifier(&drvr->inet6addr_notifier);
++#endif
++
+ /* stop firmware event handling */
+ brcmf_fweh_detach(drvr);
+ if (drvr->config)
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -48,6 +48,8 @@
+ */
+ #define BRCMF_DRIVER_FIRMWARE_VERSION_LEN 32
+
++#define NDOL_MAX_ENTRIES 8
++
+ /**
+ * struct brcmf_ampdu_rx_reorder - AMPDU receive reorder info
+ *
+@@ -143,6 +145,7 @@ struct brcmf_pub {
+ #endif
+
+ struct notifier_block inetaddr_notifier;
++ struct notifier_block inet6addr_notifier;
+ struct brcmf_mp_device *settings;
+ };
+
+@@ -175,6 +178,7 @@ enum brcmf_netif_stop_reason {
+ * @stats: interface specific network statistics.
+ * @setmacaddr_work: worker object for setting mac address.
+ * @multicast_work: worker object for multicast provisioning.
++ * @ndoffload_work: worker object for neighbor discovery offload configuration.
+ * @fws_desc: interface specific firmware-signalling descriptor.
+ * @ifidx: interface index in device firmware.
+ * @bsscfgidx: index of bss associated with this interface.
+@@ -191,6 +195,7 @@ struct brcmf_if {
+ struct net_device_stats stats;
+ struct work_struct setmacaddr_work;
+ struct work_struct multicast_work;
++ struct work_struct ndoffload_work;
+ struct brcmf_fws_mac_descriptor *fws_desc;
+ int ifidx;
+ s32 bsscfgidx;
+@@ -199,6 +204,8 @@ struct brcmf_if {
+ spinlock_t netif_stop_lock;
+ atomic_t pend_8021x_cnt;
+ wait_queue_head_t pend_8021x_wait;
++ struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES];
++ u8 ipv6addr_idx;
+ };
+
+ struct brcmf_skb_reorder_data {
diff --git a/package/kernel/mac80211/patches/344-0007-brcmfmac-check-return-for-ARP-ip-setting-iovar.patch b/package/kernel/mac80211/patches/344-0007-brcmfmac-check-return-for-ARP-ip-setting-iovar.patch
new file mode 100644
index 0000000000..68de8ed2a2
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0007-brcmfmac-check-return-for-ARP-ip-setting-iovar.patch
@@ -0,0 +1,38 @@
+From: Franky Lin <frankyl@broadcom.com>
+Date: Wed, 17 Feb 2016 11:26:56 +0100
+Subject: [PATCH] brcmfmac: check return for ARP ip setting iovar
+
+The return value of iovar set function should be saved and checked.
+
+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/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1039,14 +1039,14 @@ static int brcmf_inetaddr_changed(struct
+ return NOTIFY_OK;
+ }
+ for (i = 0; i < ARPOL_MAX_ENTRIES; i++) {
+- if (addr_table[i] != 0) {
+- brcmf_fil_iovar_data_set(ifp,
+- "arp_hostip", &addr_table[i],
+- sizeof(addr_table[i]));
+- if (ret)
+- brcmf_err("add arp ip err %d\n",
+- ret);
+- }
++ if (addr_table[i] == 0)
++ continue;
++ ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip",
++ &addr_table[i],
++ sizeof(addr_table[i]));
++ if (ret)
++ brcmf_err("add arp ip err %d\n",
++ ret);
+ }
+ }
+ break;
diff --git a/package/kernel/mac80211/patches/344-0011-brcmfmac-remove-pcie-gen1-support.patch b/package/kernel/mac80211/patches/344-0011-brcmfmac-remove-pcie-gen1-support.patch
new file mode 100644
index 0000000000..f99f6dbf07
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0011-brcmfmac-remove-pcie-gen1-support.patch
@@ -0,0 +1,221 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:00 +0100
+Subject: [PATCH] brcmfmac: remove pcie gen1 support
+
+The PCIE bus driver supports older gen1 (v1) chips, but there is no
+actual device which is using this older pcie core which is supported
+by brcmfmac. Remove all gen1 related code.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -100,9 +100,6 @@ static struct brcmf_firmware_mapping brc
+ #define BRCMF_PCIE_PCIE2REG_CONFIGDATA 0x124
+ #define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX 0x140
+
+-#define BRCMF_PCIE_GENREV1 1
+-#define BRCMF_PCIE_GENREV2 2
+-
+ #define BRCMF_PCIE2_INTA 0x01
+ #define BRCMF_PCIE2_INTB 0x02
+
+@@ -257,9 +254,7 @@ struct brcmf_pciedev_info {
+ u32 ram_size;
+ struct brcmf_chip *ci;
+ u32 coreid;
+- u32 generic_corerev;
+ struct brcmf_pcie_shared_info shared;
+- void (*ringbell)(struct brcmf_pciedev_info *devinfo);
+ wait_queue_head_t mbdata_resp_wait;
+ bool mbdata_completed;
+ bool irq_allocated;
+@@ -746,68 +741,22 @@ static void brcmf_pcie_bus_console_read(
+ }
+
+
+-static __used void brcmf_pcie_ringbell_v1(struct brcmf_pciedev_info *devinfo)
+-{
+- u32 reg_value;
+-
+- brcmf_dbg(PCIE, "RING !\n");
+- reg_value = brcmf_pcie_read_reg32(devinfo,
+- BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+- reg_value |= BRCMF_PCIE2_INTB;
+- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+- reg_value);
+-}
+-
+-
+-static void brcmf_pcie_ringbell_v2(struct brcmf_pciedev_info *devinfo)
+-{
+- brcmf_dbg(PCIE, "RING !\n");
+- /* Any arbitrary value will do, lets use 1 */
+- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX, 1);
+-}
+-
+-
+ static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
+ {
+- if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1)
+- pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTMASK,
+- 0);
+- else
+- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
+- 0);
++ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, 0);
+ }
+
+
+ static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
+ {
+- if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1)
+- pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTMASK,
+- BRCMF_PCIE_INT_DEF);
+- else
+- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
+- BRCMF_PCIE_MB_INT_D2H_DB |
+- BRCMF_PCIE_MB_INT_FN0_0 |
+- BRCMF_PCIE_MB_INT_FN0_1);
++ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
++ BRCMF_PCIE_MB_INT_D2H_DB |
++ BRCMF_PCIE_MB_INT_FN0_0 |
++ BRCMF_PCIE_MB_INT_FN0_1);
+ }
+
+
+-static irqreturn_t brcmf_pcie_quick_check_isr_v1(int irq, void *arg)
+-{
+- struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+- u32 status;
+-
+- status = 0;
+- pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTSTATUS, &status);
+- if (status) {
+- brcmf_pcie_intr_disable(devinfo);
+- brcmf_dbg(PCIE, "Enter\n");
+- return IRQ_WAKE_THREAD;
+- }
+- return IRQ_NONE;
+-}
+-
+-
+-static irqreturn_t brcmf_pcie_quick_check_isr_v2(int irq, void *arg)
++static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)
+ {
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+
+@@ -820,29 +769,7 @@ static irqreturn_t brcmf_pcie_quick_chec
+ }
+
+
+-static irqreturn_t brcmf_pcie_isr_thread_v1(int irq, void *arg)
+-{
+- struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+- const struct pci_dev *pdev = devinfo->pdev;
+- u32 status;
+-
+- devinfo->in_irq = true;
+- status = 0;
+- pci_read_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, &status);
+- brcmf_dbg(PCIE, "Enter %x\n", status);
+- if (status) {
+- pci_write_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, status);
+- if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+- brcmf_proto_msgbuf_rx_trigger(&devinfo->pdev->dev);
+- }
+- if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+- brcmf_pcie_intr_enable(devinfo);
+- devinfo->in_irq = false;
+- return IRQ_HANDLED;
+-}
+-
+-
+-static irqreturn_t brcmf_pcie_isr_thread_v2(int irq, void *arg)
++static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
+ {
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+ u32 status;
+@@ -879,28 +806,14 @@ static int brcmf_pcie_request_irq(struct
+ brcmf_pcie_intr_disable(devinfo);
+
+ brcmf_dbg(PCIE, "Enter\n");
+- /* is it a v1 or v2 implementation */
++
+ pci_enable_msi(pdev);
+- if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
+- if (request_threaded_irq(pdev->irq,
+- brcmf_pcie_quick_check_isr_v1,
+- brcmf_pcie_isr_thread_v1,
+- IRQF_SHARED, "brcmf_pcie_intr",
+- devinfo)) {
+- pci_disable_msi(pdev);
+- brcmf_err("Failed to request IRQ %d\n", pdev->irq);
+- return -EIO;
+- }
+- } else {
+- if (request_threaded_irq(pdev->irq,
+- brcmf_pcie_quick_check_isr_v2,
+- brcmf_pcie_isr_thread_v2,
+- IRQF_SHARED, "brcmf_pcie_intr",
+- devinfo)) {
+- pci_disable_msi(pdev);
+- brcmf_err("Failed to request IRQ %d\n", pdev->irq);
+- return -EIO;
+- }
++ if (request_threaded_irq(pdev->irq, brcmf_pcie_quick_check_isr,
++ brcmf_pcie_isr_thread, IRQF_SHARED,
++ "brcmf_pcie_intr", devinfo)) {
++ pci_disable_msi(pdev);
++ brcmf_err("Failed to request IRQ %d\n", pdev->irq);
++ return -EIO;
+ }
+ devinfo->irq_allocated = true;
+ return 0;
+@@ -931,16 +844,9 @@ static void brcmf_pcie_release_irq(struc
+ if (devinfo->in_irq)
+ brcmf_err("Still in IRQ (processing) !!!\n");
+
+- if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
+- status = 0;
+- pci_read_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, &status);
+- pci_write_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, status);
+- } else {
+- status = brcmf_pcie_read_reg32(devinfo,
+- BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+- status);
+- }
++ status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
++ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, status);
++
+ devinfo->irq_allocated = false;
+ }
+
+@@ -989,7 +895,9 @@ static int brcmf_pcie_ring_mb_ring_bell(
+ if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+ return -EIO;
+
+- devinfo->ringbell(devinfo);
++ brcmf_dbg(PCIE, "RING !\n");
++ /* Any arbitrary value will do, lets use 1 */
++ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX, 1);
+
+ return 0;
+ }
+@@ -1503,9 +1411,6 @@ static int brcmf_pcie_download_fw_nvram(
+ u32 address;
+ u32 resetintr;
+
+- devinfo->ringbell = brcmf_pcie_ringbell_v2;
+- devinfo->generic_corerev = BRCMF_PCIE_GENREV2;
+-
+ brcmf_dbg(PCIE, "Halt ARM.\n");
+ err = brcmf_pcie_enter_download_state(devinfo);
+ if (err)
diff --git a/package/kernel/mac80211/patches/344-0012-brcmfmac-increase-timeout-for-tx-eapol.patch b/package/kernel/mac80211/patches/344-0012-brcmfmac-increase-timeout-for-tx-eapol.patch
index c529ff2c0e..4adfc2dc64 100644
--- a/package/kernel/mac80211/patches/344-0012-brcmfmac-increase-timeout-for-tx-eapol.patch
+++ b/package/kernel/mac80211/patches/344-0012-brcmfmac-increase-timeout-for-tx-eapol.patch
@@ -19,7 +19,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -40,7 +40,7 @@ MODULE_AUTHOR("Broadcom Corporation");
+@@ -42,7 +42,7 @@ MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/package/kernel/mac80211/patches/344-0013-brcmfmac-move-module-init-and-exit-to-common.patch b/package/kernel/mac80211/patches/344-0013-brcmfmac-move-module-init-and-exit-to-common.patch
new file mode 100644
index 0000000000..bd62781188
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0013-brcmfmac-move-module-init-and-exit-to-common.patch
@@ -0,0 +1,135 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:02 +0100
+Subject: [PATCH] brcmfmac: move module init and exit to common
+
+In preparation of module parameters for all devices the module init
+and exit routines are moved to the common file.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+@@ -28,6 +28,10 @@
+ #include "tracepoint.h"
+ #include "common.h"
+
++MODULE_AUTHOR("Broadcom Corporation");
++MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
++MODULE_LICENSE("Dual BSD/GPL");
++
+ const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
+@@ -221,7 +225,7 @@ void __brcmf_dbg(u32 level, const char *
+ }
+ #endif
+
+-void brcmf_mp_attach(void)
++static void brcmf_mp_attach(void)
+ {
+ strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
+ BRCMF_FW_ALTPATH_LEN);
+@@ -249,3 +253,33 @@ void brcmf_mp_device_detach(struct brcmf
+ kfree(drvr->settings);
+ }
+
++static int __init brcmfmac_module_init(void)
++{
++ int err;
++
++ /* Initialize debug system first */
++ brcmf_debugfs_init();
++
++#ifdef CPTCFG_BRCMFMAC_SDIO
++ brcmf_sdio_init();
++#endif
++ /* Initialize global module paramaters */
++ brcmf_mp_attach();
++
++ /* Continue the initialization by registering the different busses */
++ err = brcmf_core_init();
++ if (err)
++ brcmf_debugfs_exit();
++
++ return err;
++}
++
++static void __exit brcmfmac_module_exit(void)
++{
++ brcmf_core_exit();
++ brcmf_debugfs_exit();
++}
++
++module_init(brcmfmac_module_init);
++module_exit(brcmfmac_module_exit);
++
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+@@ -89,7 +89,6 @@ struct brcmf_mp_device {
+ struct cc_translate *country_codes;
+ };
+
+-void brcmf_mp_attach(void);
+ int brcmf_mp_device_attach(struct brcmf_pub *drvr);
+ void brcmf_mp_device_detach(struct brcmf_pub *drvr);
+ #ifdef DEBUG
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -38,10 +38,6 @@
+ #include "pcie.h"
+ #include "common.h"
+
+-MODULE_AUTHOR("Broadcom Corporation");
+-MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
+-MODULE_LICENSE("Dual BSD/GPL");
+-
+ #define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950)
+
+ /* AMPDU rx reordering definitions */
+@@ -1422,19 +1418,15 @@ static void brcmf_driver_register(struct
+ }
+ static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
+
+-static int __init brcmfmac_module_init(void)
++int __init brcmf_core_init(void)
+ {
+- brcmf_debugfs_init();
+-#ifdef CPTCFG_BRCMFMAC_SDIO
+- brcmf_sdio_init();
+-#endif
+ if (!schedule_work(&brcmf_driver_work))
+ return -EBUSY;
+
+ return 0;
+ }
+
+-static void __exit brcmfmac_module_exit(void)
++void __exit brcmf_core_exit(void)
+ {
+ cancel_work_sync(&brcmf_driver_work);
+
+@@ -1447,8 +1439,5 @@ static void __exit brcmfmac_module_exit(
+ #ifdef CPTCFG_BRCMFMAC_PCIE
+ brcmf_pcie_exit();
+ #endif
+- brcmf_debugfs_exit();
+ }
+
+-module_init(brcmfmac_module_init);
+-module_exit(brcmfmac_module_exit);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -227,5 +227,7 @@ void brcmf_txflowblock_if(struct brcmf_i
+ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
+ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
+ void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
++int __init brcmf_core_init(void);
++void __exit brcmf_core_exit(void);
+
+ #endif /* BRCMFMAC_CORE_H */
diff --git a/package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch b/package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch
new file mode 100644
index 0000000000..577ca8ed28
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0014-brcmfmac-add-wowl-gtk-rekeying-offload-support.patch
@@ -0,0 +1,260 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:03 +0100
+Subject: [PATCH] brcmfmac: add wowl gtk rekeying offload support
+
+This patch adds support for gtk rekeying offload and for gtk
+rekeying failure during wowl mode.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -3526,6 +3526,10 @@ static void brcmf_report_wowl_wakeind(st
+ else
+ wakeup_data.net_detect = cfg->wowl.nd_info;
+ }
++ if (wakeind & BRCMF_WOWL_GTK_FAILURE) {
++ brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_GTK_FAILURE\n");
++ wakeup_data.gtk_rekey_failure = true;
++ }
+ } else {
+ wakeup = NULL;
+ }
+@@ -3607,6 +3611,8 @@ static void brcmf_configure_wowl(struct
+ brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
+ brcmf_wowl_nd_results);
+ }
++ if (wowl->gtk_rekey_failure)
++ wowl_config |= BRCMF_WOWL_GTK_FAILURE;
+ if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
+ wowl_config |= BRCMF_WOWL_UNASSOC;
+
+@@ -4874,7 +4880,32 @@ static int brcmf_cfg80211_tdls_oper(stru
+ return ret;
+ }
+
+-static struct cfg80211_ops wl_cfg80211_ops = {
++#ifdef CONFIG_PM
++static int
++brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
++ struct cfg80211_gtk_rekey_data *gtk)
++{
++ struct brcmf_if *ifp = netdev_priv(ndev);
++ struct brcmf_gtk_keyinfo_le gtk_le;
++ int ret;
++
++ brcmf_dbg(TRACE, "Enter, bssidx=%d\n", ifp->bsscfgidx);
++
++ memcpy(gtk_le.kck, gtk->kck, sizeof(gtk_le.kck));
++ memcpy(gtk_le.kek, gtk->kek, sizeof(gtk_le.kek));
++ memcpy(gtk_le.replay_counter, gtk->replay_ctr,
++ sizeof(gtk_le.replay_counter));
++
++ ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", &gtk_le,
++ sizeof(gtk_le));
++ if (ret < 0)
++ brcmf_err("gtk_key_info iovar failed: ret=%d\n", ret);
++
++ return ret;
++}
++#endif
++
++static struct cfg80211_ops brcmf_cfg80211_ops = {
+ .add_virtual_intf = brcmf_cfg80211_add_iface,
+ .del_virtual_intf = brcmf_cfg80211_del_iface,
+ .change_virtual_intf = brcmf_cfg80211_change_iface,
+@@ -6139,19 +6170,18 @@ static void brcmf_wiphy_wowl_params(stru
+ {
+ #ifdef CONFIG_PM
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+- s32 err;
+- u32 wowl_cap;
+
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
+- err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
+- if (!err) {
+- if (wowl_cap & BRCMF_WOWL_PFN_FOUND) {
+- brcmf_wowlan_support.flags |=
+- WIPHY_WOWLAN_NET_DETECT;
+- init_waitqueue_head(&cfg->wowl.nd_data_wait);
+- }
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ND)) {
++ brcmf_wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT;
++ init_waitqueue_head(&cfg->wowl.nd_data_wait);
+ }
+ }
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) {
++ brcmf_wowlan_support.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY;
++ brcmf_wowlan_support.flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE;
++ }
++
+ wiphy->wowlan = &brcmf_wowlan_support;
+ #endif
+ }
+@@ -6538,6 +6568,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
+ struct brcmf_cfg80211_info *cfg;
+ struct wiphy *wiphy;
++ struct cfg80211_ops *ops;
+ struct brcmf_cfg80211_vif *vif;
+ struct brcmf_if *ifp;
+ s32 err = 0;
+@@ -6549,8 +6580,17 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ return NULL;
+ }
+
++ ops = kzalloc(sizeof(*ops), GFP_KERNEL);
++ if (!ops)
++ return NULL;
++
++ memcpy(ops, &brcmf_cfg80211_ops, sizeof(*ops));
+ ifp = netdev_priv(ndev);
+- wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
++#ifdef CONFIG_PM
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
++ ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
++#endif
++ wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info));
+ if (!wiphy) {
+ brcmf_err("Could not allocate wiphy device\n");
+ return NULL;
+@@ -6560,6 +6600,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+
+ cfg = wiphy_priv(wiphy);
+ cfg->wiphy = wiphy;
++ cfg->ops = ops;
+ cfg->pub = drvr;
+ init_vif_event(&cfg->vif_event);
+ INIT_LIST_HEAD(&cfg->vif_list);
+@@ -6686,6 +6727,7 @@ priv_out:
+ ifp->vif = NULL;
+ wiphy_out:
+ brcmf_free_wiphy(wiphy);
++ kfree(ops);
+ return NULL;
+ }
+
+@@ -6696,6 +6738,7 @@ void brcmf_cfg80211_detach(struct brcmf_
+
+ brcmf_btcoex_detach(cfg);
+ wiphy_unregister(cfg->wiphy);
++ kfree(cfg->ops);
+ wl_deinit_priv(cfg);
+ brcmf_free_wiphy(cfg->wiphy);
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -256,6 +256,7 @@ struct brcmf_cfg80211_wowl {
+ * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
+ *
+ * @wiphy: wiphy object for cfg80211 interface.
++ * @ops: pointer to copy of ops as registered with wiphy object.
+ * @conf: dongle configuration.
+ * @p2p: peer-to-peer specific information.
+ * @btcoex: Bluetooth coexistence information.
+@@ -288,6 +289,7 @@ struct brcmf_cfg80211_wowl {
+ */
+ struct brcmf_cfg80211_info {
+ struct wiphy *wiphy;
++ struct cfg80211_ops *ops;
+ struct brcmf_cfg80211_conf *conf;
+ struct brcmf_p2p_info p2p;
+ struct brcmf_btcoex_info *btcoex;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+@@ -136,6 +136,7 @@ void brcmf_feat_attach(struct brcmf_pub
+ {
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
+ struct brcmf_pno_macaddr_le pfn_mac;
++ u32 wowl_cap;
+ s32 err;
+
+ brcmf_feat_firmware_capabilities(ifp);
+@@ -143,6 +144,17 @@ void brcmf_feat_attach(struct brcmf_pub
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
+ if (drvr->bus_if->wowl_supported)
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) {
++ err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
++ if (!err) {
++ if (wowl_cap & BRCMF_WOWL_PFN_FOUND)
++ ifp->drvr->feat_flags |=
++ BIT(BRCMF_FEAT_WOWL_ND);
++ if (wowl_cap & BRCMF_WOWL_GTK_FAILURE)
++ ifp->drvr->feat_flags |=
++ BIT(BRCMF_FEAT_WOWL_GTK);
++ }
++ }
+ /* MBSS does not work for 43362 */
+ if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID)
+ ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+@@ -27,6 +27,8 @@
+ * RSDB: Real Simultaneous Dual Band
+ * TDLS: Tunneled Direct Link Setup
+ * SCAN_RANDOM_MAC: Random MAC during (net detect) scheduled scan.
++ * WOWL_ND: WOWL net detect (PNO)
++ * WOWL_GTK: (WOWL) GTK rekeying offload
+ */
+ #define BRCMF_FEAT_LIST \
+ BRCMF_FEAT_DEF(MBSS) \
+@@ -36,7 +38,9 @@
+ BRCMF_FEAT_DEF(P2P) \
+ BRCMF_FEAT_DEF(RSDB) \
+ BRCMF_FEAT_DEF(TDLS) \
+- BRCMF_FEAT_DEF(SCAN_RANDOM_MAC)
++ BRCMF_FEAT_DEF(SCAN_RANDOM_MAC) \
++ BRCMF_FEAT_DEF(WOWL_ND) \
++ BRCMF_FEAT_DEF(WOWL_GTK)
+
+ /*
+ * Quirks:
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+@@ -111,7 +111,9 @@
+ /* Wakeup if received matched secured pattern: */
+ #define BRCMF_WOWL_SECURE (1 << 25)
+ /* Wakeup on finding preferred network */
+-#define BRCMF_WOWL_PFN_FOUND (1 << 26)
++#define BRCMF_WOWL_PFN_FOUND (1 << 27)
++/* Wakeup on receiving pairwise key EAP packets: */
++#define WIPHY_WOWL_EAP_PK (1 << 28)
+ /* Link Down indication in WoWL mode: */
+ #define BRCMF_WOWL_LINKDOWN (1 << 31)
+
+@@ -136,6 +138,10 @@
+
+ #define BRCMF_MCSSET_LEN 16
+
++#define BRCMF_RSN_KCK_LENGTH 16
++#define BRCMF_RSN_KEK_LENGTH 16
++#define BRCMF_RSN_REPLAY_LEN 8
++
+ /* join preference types for join_pref iovar */
+ enum brcmf_join_pref_types {
+ BRCMF_JOIN_PREF_RSSI = 1,
+@@ -789,4 +795,17 @@ struct brcmf_pktcnt_le {
+ __le32 rx_ocast_good_pkt;
+ };
+
++/**
++ * struct brcmf_gtk_keyinfo_le - GTP rekey data
++ *
++ * @kck: key confirmation key.
++ * @kek: key encryption key.
++ * @replay_counter: replay counter.
++ */
++struct brcmf_gtk_keyinfo_le {
++ u8 kck[BRCMF_RSN_KCK_LENGTH];
++ u8 kek[BRCMF_RSN_KEK_LENGTH];
++ u8 replay_counter[BRCMF_RSN_REPLAY_LEN];
++};
++
+ #endif /* FWIL_TYPES_H_ */
diff --git a/package/kernel/mac80211/patches/344-0015-brcmfmac-move-platform-data-retrieval-code-to-common.patch b/package/kernel/mac80211/patches/344-0015-brcmfmac-move-platform-data-retrieval-code-to-common.patch
new file mode 100644
index 0000000000..2685238925
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0015-brcmfmac-move-platform-data-retrieval-code-to-common.patch
@@ -0,0 +1,385 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:04 +0100
+Subject: [PATCH] brcmfmac: move platform data retrieval code to common
+
+In preparation of module parameters for all devices the module
+platform data retrieval is moved from sdio to common. It is still
+only used for sdio devices.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -27,8 +27,6 @@
+ #include <linux/mmc/sdio_func.h>
+ #include <linux/mmc/card.h>
+ #include <linux/mmc/host.h>
+-#include <linux/platform_device.h>
+-#include <linux/platform_data/brcmfmac-sdio.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/suspend.h>
+ #include <linux/errno.h>
+@@ -46,7 +44,6 @@
+ #include "bus.h"
+ #include "debug.h"
+ #include "sdio.h"
+-#include "of.h"
+ #include "core.h"
+ #include "common.h"
+
+@@ -106,18 +103,18 @@ static void brcmf_sdiod_dummy_irqhandler
+
+ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
+ {
++ struct brcmfmac_sdio_platform_data *pdata;
+ int ret = 0;
+ u8 data;
+ u32 addr, gpiocontrol;
+ unsigned long flags;
+
+- if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
++ pdata = sdiodev->pdata;
++ if ((pdata) && (pdata->oob_irq_supported)) {
+ brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
+- sdiodev->pdata->oob_irq_nr);
+- ret = request_irq(sdiodev->pdata->oob_irq_nr,
+- brcmf_sdiod_oob_irqhandler,
+- sdiodev->pdata->oob_irq_flags,
+- "brcmf_oob_intr",
++ pdata->oob_irq_nr);
++ ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler,
++ pdata->oob_irq_flags, "brcmf_oob_intr",
+ &sdiodev->func[1]->dev);
+ if (ret != 0) {
+ brcmf_err("request_irq failed %d\n", ret);
+@@ -129,7 +126,7 @@ int brcmf_sdiod_intr_register(struct brc
+ sdiodev->irq_en = true;
+ spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
+
+- ret = enable_irq_wake(sdiodev->pdata->oob_irq_nr);
++ ret = enable_irq_wake(pdata->oob_irq_nr);
+ if (ret != 0) {
+ brcmf_err("enable_irq_wake failed %d\n", ret);
+ return ret;
+@@ -158,7 +155,7 @@ int brcmf_sdiod_intr_register(struct brc
+
+ /* redirect, configure and enable io for interrupt signal */
+ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
+- if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
++ if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
+ data |= SDIO_SEPINT_ACT_HI;
+ brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
+
+@@ -176,9 +173,12 @@ int brcmf_sdiod_intr_register(struct brc
+
+ int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev)
+ {
++ struct brcmfmac_sdio_platform_data *pdata;
++
+ brcmf_dbg(SDIO, "Entering\n");
+
+- if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
++ pdata = sdiodev->pdata;
++ if ((pdata) && (pdata->oob_irq_supported)) {
+ sdio_claim_host(sdiodev->func[1]);
+ brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
+ brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+@@ -187,11 +187,10 @@ int brcmf_sdiod_intr_unregister(struct b
+ if (sdiodev->oob_irq_requested) {
+ sdiodev->oob_irq_requested = false;
+ if (sdiodev->irq_wake) {
+- disable_irq_wake(sdiodev->pdata->oob_irq_nr);
++ disable_irq_wake(pdata->oob_irq_nr);
+ sdiodev->irq_wake = false;
+ }
+- free_irq(sdiodev->pdata->oob_irq_nr,
+- &sdiodev->func[1]->dev);
++ free_irq(pdata->oob_irq_nr, &sdiodev->func[1]->dev);
+ sdiodev->irq_en = false;
+ }
+ } else {
+@@ -1103,8 +1102,6 @@ static const struct sdio_device_id brcmf
+ };
+ MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
+
+-static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
+-
+
+ static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
+ int val)
+@@ -1167,10 +1164,7 @@ static int brcmf_ops_sdio_probe(struct s
+ dev_set_drvdata(&func->dev, bus_if);
+ dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
+ sdiodev->dev = &sdiodev->func[1]->dev;
+- sdiodev->pdata = brcmfmac_sdio_pdata;
+-
+- if (!sdiodev->pdata)
+- brcmf_of_probe(sdiodev);
++ sdiodev->pdata = brcmf_get_module_param(sdiodev->dev);
+
+ #ifdef CONFIG_PM_SLEEP
+ /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
+@@ -1296,7 +1290,7 @@ static const struct dev_pm_ops brcmf_sdi
+ static struct sdio_driver brcmf_sdmmc_driver = {
+ .probe = brcmf_ops_sdio_probe,
+ .remove = brcmf_ops_sdio_remove,
+- .name = BRCMFMAC_SDIO_PDATA_NAME,
++ .name = KBUILD_MODNAME,
+ .id_table = brcmf_sdmmc_ids,
+ .drv = {
+ .owner = THIS_MODULE,
+@@ -1306,37 +1300,6 @@ static struct sdio_driver brcmf_sdmmc_dr
+ },
+ };
+
+-static int __init brcmf_sdio_pd_probe(struct platform_device *pdev)
+-{
+- brcmf_dbg(SDIO, "Enter\n");
+-
+- brcmfmac_sdio_pdata = dev_get_platdata(&pdev->dev);
+-
+- if (brcmfmac_sdio_pdata->power_on)
+- brcmfmac_sdio_pdata->power_on();
+-
+- return 0;
+-}
+-
+-static int brcmf_sdio_pd_remove(struct platform_device *pdev)
+-{
+- brcmf_dbg(SDIO, "Enter\n");
+-
+- if (brcmfmac_sdio_pdata->power_off)
+- brcmfmac_sdio_pdata->power_off();
+-
+- sdio_unregister_driver(&brcmf_sdmmc_driver);
+-
+- return 0;
+-}
+-
+-static struct platform_driver brcmf_sdio_pd = {
+- .remove = brcmf_sdio_pd_remove,
+- .driver = {
+- .name = BRCMFMAC_SDIO_PDATA_NAME,
+- }
+-};
+-
+ void brcmf_sdio_register(void)
+ {
+ int ret;
+@@ -1350,19 +1313,6 @@ void brcmf_sdio_exit(void)
+ {
+ brcmf_dbg(SDIO, "Enter\n");
+
+- if (brcmfmac_sdio_pdata)
+- platform_driver_unregister(&brcmf_sdio_pd);
+- else
+- sdio_unregister_driver(&brcmf_sdmmc_driver);
++ sdio_unregister_driver(&brcmf_sdmmc_driver);
+ }
+
+-void __init brcmf_sdio_init(void)
+-{
+- int ret;
+-
+- brcmf_dbg(SDIO, "Enter\n");
+-
+- ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
+- if (ret == -ENODEV)
+- brcmf_dbg(SDIO, "No platform data available.\n");
+-}
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+@@ -27,6 +27,7 @@
+ #include "fwil_types.h"
+ #include "tracepoint.h"
+ #include "common.h"
++#include "of.h"
+
+ MODULE_AUTHOR("Broadcom Corporation");
+ MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
+@@ -79,6 +80,7 @@ module_param_named(ignore_probe_fail, br
+ MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
+ #endif
+
++static struct brcmfmac_sdio_platform_data *brcmfmac_pdata;
+ struct brcmf_mp_global_t brcmf_mp_global;
+
+ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
+@@ -231,6 +233,13 @@ static void brcmf_mp_attach(void)
+ BRCMF_FW_ALTPATH_LEN);
+ }
+
++struct brcmfmac_sdio_platform_data *brcmf_get_module_param(struct device *dev)
++{
++ if (!brcmfmac_pdata)
++ brcmf_of_probe(dev, &brcmfmac_pdata);
++ return brcmfmac_pdata;
++}
++
+ int brcmf_mp_device_attach(struct brcmf_pub *drvr)
+ {
+ drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC);
+@@ -253,6 +262,35 @@ void brcmf_mp_device_detach(struct brcmf
+ kfree(drvr->settings);
+ }
+
++static int __init brcmf_common_pd_probe(struct platform_device *pdev)
++{
++ brcmf_dbg(INFO, "Enter\n");
++
++ brcmfmac_pdata = dev_get_platdata(&pdev->dev);
++
++ if (brcmfmac_pdata->power_on)
++ brcmfmac_pdata->power_on();
++
++ return 0;
++}
++
++static int brcmf_common_pd_remove(struct platform_device *pdev)
++{
++ brcmf_dbg(INFO, "Enter\n");
++
++ if (brcmfmac_pdata->power_off)
++ brcmfmac_pdata->power_off();
++
++ return 0;
++}
++
++static struct platform_driver brcmf_pd = {
++ .remove = brcmf_common_pd_remove,
++ .driver = {
++ .name = BRCMFMAC_SDIO_PDATA_NAME,
++ }
++};
++
+ static int __init brcmfmac_module_init(void)
+ {
+ int err;
+@@ -260,16 +298,21 @@ static int __init brcmfmac_module_init(v
+ /* Initialize debug system first */
+ brcmf_debugfs_init();
+
+-#ifdef CPTCFG_BRCMFMAC_SDIO
+- brcmf_sdio_init();
+-#endif
++ /* Get the platform data (if available) for our devices */
++ err = platform_driver_probe(&brcmf_pd, brcmf_common_pd_probe);
++ if (err == -ENODEV)
++ brcmf_dbg(INFO, "No platform data available.\n");
++
+ /* Initialize global module paramaters */
+ brcmf_mp_attach();
+
+ /* Continue the initialization by registering the different busses */
+ err = brcmf_core_init();
+- if (err)
++ if (err) {
+ brcmf_debugfs_exit();
++ if (brcmfmac_pdata)
++ platform_driver_unregister(&brcmf_pd);
++ }
+
+ return err;
+ }
+@@ -277,6 +320,8 @@ static int __init brcmfmac_module_init(v
+ static void __exit brcmfmac_module_exit(void)
+ {
+ brcmf_core_exit();
++ if (brcmfmac_pdata)
++ platform_driver_unregister(&brcmf_pd);
+ brcmf_debugfs_exit();
+ }
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+@@ -15,6 +15,8 @@
+ #ifndef BRCMFMAC_COMMON_H
+ #define BRCMFMAC_COMMON_H
+
++#include <linux/platform_device.h>
++#include <linux/platform_data/brcmfmac-sdio.h>
+ #include "fwil_types.h"
+
+ extern const u8 ALLFFMAC[ETH_ALEN];
+@@ -89,6 +91,7 @@ struct brcmf_mp_device {
+ struct cc_translate *country_codes;
+ };
+
++struct brcmfmac_sdio_platform_data *brcmf_get_module_param(struct device *dev);
+ int brcmf_mp_device_attach(struct brcmf_pub *drvr);
+ void brcmf_mp_device_detach(struct brcmf_pub *drvr);
+ #ifdef DEBUG
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+@@ -16,17 +16,16 @@
+ #include <linux/init.h>
+ #include <linux/of.h>
+ #include <linux/of_irq.h>
+-#include <linux/mmc/card.h>
+-#include <linux/platform_data/brcmfmac-sdio.h>
+-#include <linux/mmc/sdio_func.h>
+
+ #include <defs.h>
+ #include "debug.h"
+-#include "sdio.h"
++#include "core.h"
++#include "common.h"
++#include "of.h"
+
+-void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
++void
++brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_platform_data **sdio)
+ {
+- struct device *dev = sdiodev->dev;
+ struct device_node *np = dev->of_node;
+ int irq;
+ u32 irqf;
+@@ -35,12 +34,12 @@ void brcmf_of_probe(struct brcmf_sdio_de
+ if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
+ return;
+
+- sdiodev->pdata = devm_kzalloc(dev, sizeof(*sdiodev->pdata), GFP_KERNEL);
+- if (!sdiodev->pdata)
++ *sdio = devm_kzalloc(dev, sizeof(*sdio), GFP_KERNEL);
++ if (!(*sdio))
+ return;
+
+ if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
+- sdiodev->pdata->drive_strength = val;
++ (*sdio)->drive_strength = val;
+
+ /* make sure there are interrupts defined in the node */
+ if (!of_find_property(np, "interrupts", NULL))
+@@ -53,7 +52,7 @@ void brcmf_of_probe(struct brcmf_sdio_de
+ }
+ irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
+
+- sdiodev->pdata->oob_irq_supported = true;
+- sdiodev->pdata->oob_irq_nr = irq;
+- sdiodev->pdata->oob_irq_flags = irqf;
++ (*sdio)->oob_irq_supported = true;
++ (*sdio)->oob_irq_nr = irq;
++ (*sdio)->oob_irq_flags = irqf;
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
+@@ -14,9 +14,11 @@
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+ #ifdef CONFIG_OF
+-void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev);
++void
++brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_platform_data **sdio);
+ #else
+-static void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
++static void brcmf_of_probe(struct device *dev,
++ struct brcmfmac_sdio_platform_data **sdio)
+ {
+ }
+ #endif /* CONFIG_OF */
diff --git a/package/kernel/mac80211/patches/344-0016-brcmfmac-keep-ARP-and-ND-offload-enabled-during-WOWL.patch b/package/kernel/mac80211/patches/344-0016-brcmfmac-keep-ARP-and-ND-offload-enabled-during-WOWL.patch
new file mode 100644
index 0000000000..4e789cfc5a
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0016-brcmfmac-keep-ARP-and-ND-offload-enabled-during-WOWL.patch
@@ -0,0 +1,69 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:05 +0100
+Subject: [PATCH] brcmfmac: keep ARP and ND offload enabled during WOWL
+
+Currently ARP and ND (IPv6 Neigbor Discovery) offload get disabled
+on entering suspend. However when firmwares support the wowl_cap
+iovar then these offload routines can be kept enabled as they
+will work during WOWL as well.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -3556,7 +3556,8 @@ static s32 brcmf_cfg80211_resume(struct
+ brcmf_report_wowl_wakeind(wiphy, ifp);
+ brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
+ brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
+- brcmf_configure_arp_nd_offload(ifp, true);
++ if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ARP_ND))
++ brcmf_configure_arp_nd_offload(ifp, true);
+ brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,
+ cfg->wowl.pre_pmmode);
+ cfg->wowl.active = false;
+@@ -3580,7 +3581,8 @@ static void brcmf_configure_wowl(struct
+
+ brcmf_dbg(TRACE, "Suspend, wowl config.\n");
+
+- brcmf_configure_arp_nd_offload(ifp, false);
++ if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ARP_ND))
++ brcmf_configure_arp_nd_offload(ifp, false);
+ brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->wowl.pre_pmmode);
+ brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX);
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+@@ -147,6 +147,7 @@ void brcmf_feat_attach(struct brcmf_pub
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) {
+ err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
+ if (!err) {
++ ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_WOWL_ARP_ND);
+ if (wowl_cap & BRCMF_WOWL_PFN_FOUND)
+ ifp->drvr->feat_flags |=
+ BIT(BRCMF_FEAT_WOWL_ND);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+@@ -29,6 +29,7 @@
+ * SCAN_RANDOM_MAC: Random MAC during (net detect) scheduled scan.
+ * WOWL_ND: WOWL net detect (PNO)
+ * WOWL_GTK: (WOWL) GTK rekeying offload
++ * WOWL_ARP_ND: ARP and Neighbor Discovery offload support during WOWL.
+ */
+ #define BRCMF_FEAT_LIST \
+ BRCMF_FEAT_DEF(MBSS) \
+@@ -40,7 +41,8 @@
+ BRCMF_FEAT_DEF(TDLS) \
+ BRCMF_FEAT_DEF(SCAN_RANDOM_MAC) \
+ BRCMF_FEAT_DEF(WOWL_ND) \
+- BRCMF_FEAT_DEF(WOWL_GTK)
++ BRCMF_FEAT_DEF(WOWL_GTK) \
++ BRCMF_FEAT_DEF(WOWL_ARP_ND)
+
+ /*
+ * Quirks:
diff --git a/package/kernel/mac80211/patches/344-0017-brcmfmac-switch-to-new-platform-data.patch b/package/kernel/mac80211/patches/344-0017-brcmfmac-switch-to-new-platform-data.patch
new file mode 100644
index 0000000000..37b68552cc
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0017-brcmfmac-switch-to-new-platform-data.patch
@@ -0,0 +1,734 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:07 +0100
+Subject: [PATCH] brcmfmac: switch to new platform data
+
+Platform data is only available for sdio. With this patch a new
+platform data structure is being used which allows for platform
+data for any device and configurable per device. This patch only
+switches to the new structure and adds support for SDIO devices.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -103,7 +103,7 @@ static void brcmf_sdiod_dummy_irqhandler
+
+ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
+ {
+- struct brcmfmac_sdio_platform_data *pdata;
++ struct brcmfmac_sdio_pd *pdata;
+ int ret = 0;
+ u8 data;
+ u32 addr, gpiocontrol;
+@@ -173,7 +173,7 @@ int brcmf_sdiod_intr_register(struct brc
+
+ int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev)
+ {
+- struct brcmfmac_sdio_platform_data *pdata;
++ struct brcmfmac_sdio_pd *pdata;
+
+ brcmf_dbg(SDIO, "Entering\n");
+
+@@ -1164,17 +1164,6 @@ static int brcmf_ops_sdio_probe(struct s
+ dev_set_drvdata(&func->dev, bus_if);
+ dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
+ sdiodev->dev = &sdiodev->func[1]->dev;
+- sdiodev->pdata = brcmf_get_module_param(sdiodev->dev);
+-
+-#ifdef CONFIG_PM_SLEEP
+- /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
+- * is true or when platform data OOB irq is true).
+- */
+- if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
+- ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
+- (sdiodev->pdata && sdiodev->pdata->oob_irq_supported)))
+- bus_if->wowl_supported = true;
+-#endif
+
+ brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -6459,8 +6459,8 @@ int brcmf_cfg80211_wait_vif_event(struct
+ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2],
+ struct brcmf_fil_country_le *ccreq)
+ {
+- struct cc_translate *country_codes;
+- struct cc_entry *cc;
++ struct brcmfmac_pd_cc *country_codes;
++ struct brcmfmac_pd_cc_entry *cc;
+ s32 found_index;
+ int i;
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+@@ -80,7 +80,7 @@ module_param_named(ignore_probe_fail, br
+ MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
+ #endif
+
+-static struct brcmfmac_sdio_platform_data *brcmfmac_pdata;
++static struct brcmfmac_platform_data *brcmfmac_pdata;
+ struct brcmf_mp_global_t brcmf_mp_global;
+
+ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
+@@ -229,15 +229,46 @@ void __brcmf_dbg(u32 level, const char *
+
+ static void brcmf_mp_attach(void)
+ {
++ /* If module param firmware path is set then this will always be used,
++ * if not set then if available use the platform data version. To make
++ * sure it gets initialized at all, always copy the module param version
++ */
+ strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
+ BRCMF_FW_ALTPATH_LEN);
++ if ((brcmfmac_pdata) && (brcmfmac_pdata->fw_alternative_path) &&
++ (brcmf_mp_global.firmware_path[0] == '\0')) {
++ strlcpy(brcmf_mp_global.firmware_path,
++ brcmfmac_pdata->fw_alternative_path,
++ BRCMF_FW_ALTPATH_LEN);
++ }
+ }
+
+-struct brcmfmac_sdio_platform_data *brcmf_get_module_param(struct device *dev)
+-{
+- if (!brcmfmac_pdata)
+- brcmf_of_probe(dev, &brcmfmac_pdata);
+- return brcmfmac_pdata;
++struct brcmfmac_sdio_pd *brcmf_get_module_param(struct device *dev,
++ enum brcmf_bus_type bus_type,
++ u32 chip, u32 chiprev)
++{
++ struct brcmfmac_sdio_pd *pdata;
++ struct brcmfmac_pd_device *device_pd;
++ int i;
++
++ if (brcmfmac_pdata) {
++ for (i = 0; i < brcmfmac_pdata->device_count; i++) {
++ device_pd = &brcmfmac_pdata->devices[i];
++ if ((device_pd->bus_type == bus_type) &&
++ (device_pd->id == chip) &&
++ ((device_pd->rev == chiprev) ||
++ (device_pd->rev == -1))) {
++ brcmf_dbg(INFO, "Platform data for device found\n");
++ if (device_pd->bus_type == BRCMF_BUSTYPE_SDIO)
++ return &device_pd->bus.sdio;
++ break;
++ }
++ }
++ }
++ pdata = NULL;
++ brcmf_of_probe(dev, &pdata);
++
++ return pdata;
+ }
+
+ int brcmf_mp_device_attach(struct brcmf_pub *drvr)
+@@ -287,7 +318,7 @@ static int brcmf_common_pd_remove(struct
+ static struct platform_driver brcmf_pd = {
+ .remove = brcmf_common_pd_remove,
+ .driver = {
+- .name = BRCMFMAC_SDIO_PDATA_NAME,
++ .name = BRCMFMAC_PDATA_NAME,
+ }
+ };
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+@@ -16,7 +16,7 @@
+ #define BRCMFMAC_COMMON_H
+
+ #include <linux/platform_device.h>
+-#include <linux/platform_data/brcmfmac-sdio.h>
++#include <linux/platform_data/brcmfmac.h>
+ #include "fwil_types.h"
+
+ extern const u8 ALLFFMAC[ETH_ALEN];
+@@ -43,33 +43,6 @@ struct brcmf_mp_global_t {
+ extern struct brcmf_mp_global_t brcmf_mp_global;
+
+ /**
+- * struct cc_entry - Struct for translating user space country code (iso3166) to
+- * firmware country code and revision.
+- *
+- * @iso3166: iso3166 alpha 2 country code string.
+- * @cc: firmware country code string.
+- * @rev: firmware country code revision.
+- */
+-struct cc_entry {
+- char iso3166[BRCMF_COUNTRY_BUF_SZ];
+- char cc[BRCMF_COUNTRY_BUF_SZ];
+- s32 rev;
+-};
+-
+-/**
+- * struct cc_translate - Struct for translating country codes as set by user
+- * space to a country code and rev which can be used by
+- * firmware.
+- *
+- * @table_size: number of entries in table (> 0)
+- * @table: dynamic array of 1 or more elements with translation information.
+- */
+-struct cc_translate {
+- int table_size;
+- struct cc_entry table[0];
+-};
+-
+-/**
+ * struct brcmf_mp_device - Device module paramaters.
+ *
+ * @sdiod_txglomsz: SDIO txglom size.
+@@ -88,10 +61,12 @@ struct brcmf_mp_device {
+ int fcmode;
+ bool roamoff;
+ bool ignore_probe_fail;
+- struct cc_translate *country_codes;
++ struct brcmfmac_pd_cc *country_codes;
+ };
+
+-struct brcmfmac_sdio_platform_data *brcmf_get_module_param(struct device *dev);
++struct brcmfmac_sdio_pd *brcmf_get_module_param(struct device *dev,
++ enum brcmf_bus_type bus_type,
++ u32 chip, u32 chiprev);
+ int brcmf_mp_device_attach(struct brcmf_pub *drvr);
+ void brcmf_mp_device_detach(struct brcmf_pub *drvr);
+ #ifdef DEBUG
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+@@ -23,8 +23,7 @@
+ #include "common.h"
+ #include "of.h"
+
+-void
+-brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_platform_data **sdio)
++void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
+ {
+ struct device_node *np = dev->of_node;
+ int irq;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
+@@ -15,10 +15,9 @@
+ */
+ #ifdef CONFIG_OF
+ void
+-brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_platform_data **sdio);
++brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio);
+ #else
+-static void brcmf_of_probe(struct device *dev,
+- struct brcmfmac_sdio_platform_data **sdio)
++static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
+ {
+ }
+ #endif /* CONFIG_OF */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -33,8 +33,6 @@
+ #include <linux/bcma/bcma.h>
+ #include <linux/debugfs.h>
+ #include <linux/vmalloc.h>
+-#include <linux/platform_data/brcmfmac-sdio.h>
+-#include <linux/moduleparam.h>
+ #include <asm/unaligned.h>
+ #include <defs.h>
+ #include <brcmu_wifi.h>
+@@ -44,6 +42,8 @@
+ #include "sdio.h"
+ #include "chip.h"
+ #include "firmware.h"
++#include "core.h"
++#include "common.h"
+
+ #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500)
+ #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500)
+@@ -3775,26 +3775,28 @@ static const struct brcmf_buscore_ops br
+ static bool
+ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
+ {
++ struct brcmf_sdio_dev *sdiodev;
+ u8 clkctl = 0;
+ int err = 0;
+ int reg_addr;
+ u32 reg_val;
+ u32 drivestrength;
+
+- sdio_claim_host(bus->sdiodev->func[1]);
++ sdiodev = bus->sdiodev;
++ sdio_claim_host(sdiodev->func[1]);
+
+ pr_debug("F1 signature read @0x18000000=0x%4x\n",
+- brcmf_sdiod_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
++ brcmf_sdiod_regrl(sdiodev, SI_ENUM_BASE, NULL));
+
+ /*
+ * Force PLL off until brcmf_chip_attach()
+ * programs PLL control regs
+ */
+
+- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
++ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ BRCMF_INIT_CLKCTL1, &err);
+ if (!err)
+- clkctl = brcmf_sdiod_regrb(bus->sdiodev,
++ clkctl = brcmf_sdiod_regrb(sdiodev,
+ SBSDIO_FUNC1_CHIPCLKCSR, &err);
+
+ if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
+@@ -3803,50 +3805,77 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+ goto fail;
+ }
+
+- bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops);
++ bus->ci = brcmf_chip_attach(sdiodev, &brcmf_sdio_buscore_ops);
+ if (IS_ERR(bus->ci)) {
+ brcmf_err("brcmf_chip_attach failed!\n");
+ bus->ci = NULL;
+ goto fail;
+ }
++ sdiodev->pdata = brcmf_get_module_param(sdiodev->dev,
++ BRCMF_BUSTYPE_SDIO,
++ bus->ci->chip,
++ bus->ci->chiprev);
++ /* platform specific configuration:
++ * alignments must be at least 4 bytes for ADMA
++ */
++ bus->head_align = ALIGNMENT;
++ bus->sgentry_align = ALIGNMENT;
++ if (sdiodev->pdata) {
++ if (sdiodev->pdata->sd_head_align > ALIGNMENT)
++ bus->head_align = sdiodev->pdata->sd_head_align;
++ if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT)
++ bus->sgentry_align = sdiodev->pdata->sd_sgentry_align;
++ }
++ /* allocate scatter-gather table. sg support
++ * will be disabled upon allocation failure.
++ */
++ brcmf_sdiod_sgtable_alloc(sdiodev);
++
++#ifdef CONFIG_PM_SLEEP
++ /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
++ * is true or when platform data OOB irq is true).
++ */
++ if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
++ ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
++ (sdiodev->pdata && sdiodev->pdata->oob_irq_supported)))
++ sdiodev->bus_if->wowl_supported = true;
++#endif
+
+ if (brcmf_sdio_kso_init(bus)) {
+ brcmf_err("error enabling KSO\n");
+ goto fail;
+ }
+
+- if ((bus->sdiodev->pdata) && (bus->sdiodev->pdata->drive_strength))
+- drivestrength = bus->sdiodev->pdata->drive_strength;
++ if ((sdiodev->pdata) && (sdiodev->pdata->drive_strength))
++ drivestrength = sdiodev->pdata->drive_strength;
+ else
+ drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
+- brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
++ brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength);
+
+ /* Set card control so an SDIO card reset does a WLAN backplane reset */
+- reg_val = brcmf_sdiod_regrb(bus->sdiodev,
+- SDIO_CCCR_BRCM_CARDCTRL, &err);
++ reg_val = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err);
+ if (err)
+ goto fail;
+
+ reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
+
+- brcmf_sdiod_regwb(bus->sdiodev,
+- SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
++ brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
+ if (err)
+ goto fail;
+
+ /* set PMUControl so a backplane reset does PMU state reload */
+ reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol);
+- reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err);
++ reg_val = brcmf_sdiod_regrl(sdiodev, reg_addr, &err);
+ if (err)
+ goto fail;
+
+ reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
+
+- brcmf_sdiod_regwl(bus->sdiodev, reg_addr, reg_val, &err);
++ brcmf_sdiod_regwl(sdiodev, reg_addr, reg_val, &err);
+ if (err)
+ goto fail;
+
+- sdio_release_host(bus->sdiodev->func[1]);
++ sdio_release_host(sdiodev->func[1]);
+
+ brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
+
+@@ -3867,7 +3896,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+ return true;
+
+ fail:
+- sdio_release_host(bus->sdiodev->func[1]);
++ sdio_release_host(sdiodev->func[1]);
+ return false;
+ }
+
+@@ -4045,18 +4074,6 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
+ bus->txminmax = BRCMF_TXMINMAX;
+ bus->tx_seq = SDPCM_SEQ_WRAP - 1;
+
+- /* platform specific configuration:
+- * alignments must be at least 4 bytes for ADMA
+- */
+- bus->head_align = ALIGNMENT;
+- bus->sgentry_align = ALIGNMENT;
+- if (sdiodev->pdata) {
+- if (sdiodev->pdata->sd_head_align > ALIGNMENT)
+- bus->head_align = sdiodev->pdata->sd_head_align;
+- if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT)
+- bus->sgentry_align = sdiodev->pdata->sd_sgentry_align;
+- }
+-
+ /* single-threaded workqueue */
+ wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM,
+ dev_name(&sdiodev->func[1]->dev));
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -184,7 +184,7 @@ struct brcmf_sdio_dev {
+ struct brcmf_sdio *bus;
+ struct device *dev;
+ struct brcmf_bus *bus_if;
+- struct brcmfmac_sdio_platform_data *pdata;
++ struct brcmfmac_sdio_pd *pdata;
+ bool oob_irq_requested;
+ bool irq_en; /* irq enable flags */
+ spinlock_t irq_en_lock;
+--- a/include/linux/platform_data/brcmfmac-sdio.h
++++ /dev/null
+@@ -1,135 +0,0 @@
+-/*
+- * Copyright (c) 2013 Broadcom Corporation
+- *
+- * Permission to use, copy, modify, and/or distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- */
+-
+-#ifndef _LINUX_BRCMFMAC_PLATFORM_H
+-#define _LINUX_BRCMFMAC_PLATFORM_H
+-
+-/*
+- * Platform specific driver functions and data. Through the platform specific
+- * device data functions can be provided to help the brcmfmac driver to
+- * operate with the device in combination with the used platform.
+- *
+- * Use the platform data in the following (similar) way:
+- *
+- *
+-#include <brcmfmac_platform.h>
+-
+-
+-static void brcmfmac_power_on(void)
+-{
+-}
+-
+-static void brcmfmac_power_off(void)
+-{
+-}
+-
+-static void brcmfmac_reset(void)
+-{
+-}
+-
+-static struct brcmfmac_sdio_platform_data brcmfmac_sdio_pdata = {
+- .power_on = brcmfmac_power_on,
+- .power_off = brcmfmac_power_off,
+- .reset = brcmfmac_reset
+-};
+-
+-static struct platform_device brcmfmac_device = {
+- .name = BRCMFMAC_SDIO_PDATA_NAME,
+- .id = PLATFORM_DEVID_NONE,
+- .dev.platform_data = &brcmfmac_sdio_pdata
+-};
+-
+-void __init brcmfmac_init_pdata(void)
+-{
+- brcmfmac_sdio_pdata.oob_irq_supported = true;
+- brcmfmac_sdio_pdata.oob_irq_nr = gpio_to_irq(GPIO_BRCMF_SDIO_OOB);
+- brcmfmac_sdio_pdata.oob_irq_flags = IORESOURCE_IRQ |
+- IORESOURCE_IRQ_HIGHLEVEL;
+- platform_device_register(&brcmfmac_device);
+-}
+- *
+- *
+- * Note: the brcmfmac can be loaded as module or be statically built-in into
+- * the kernel. If built-in then do note that it uses module_init (and
+- * module_exit) routines which equal device_initcall. So if you intend to
+- * create a module with the platform specific data for the brcmfmac and have
+- * it built-in to the kernel then use a higher initcall then device_initcall
+- * (see init.h). If this is not done then brcmfmac will load without problems
+- * but will not pickup the platform data.
+- *
+- * When the driver does not "detect" platform driver data then it will continue
+- * without reporting anything and just assume there is no data needed. Which is
+- * probably true for most platforms.
+- *
+- * Explanation of the platform_data fields:
+- *
+- * drive_strength: is the preferred drive_strength to be used for the SDIO
+- * pins. If 0 then a default value will be used. This is the target drive
+- * strength, the exact drive strength which will be used depends on the
+- * capabilities of the device.
+- *
+- * oob_irq_supported: does the board have support for OOB interrupts. SDIO
+- * in-band interrupts are relatively slow and for having less overhead on
+- * interrupt processing an out of band interrupt can be used. If the HW
+- * supports this then enable this by setting this field to true and configure
+- * the oob related fields.
+- *
+- * oob_irq_nr, oob_irq_flags: the OOB interrupt information. The values are
+- * used for registering the irq using request_irq function.
+- *
+- * broken_sg_support: flag for broken sg list support of SDIO host controller.
+- * Set this to true if the SDIO host controller has higher align requirement
+- * than 32 bytes for each scatterlist item.
+- *
+- * sd_head_align: alignment requirement for start of data buffer
+- *
+- * sd_sgentry_align: length alignment requirement for each sg entry
+- *
+- * power_on: This function is called by the brcmfmac when the module gets
+- * loaded. This can be particularly useful for low power devices. The platform
+- * spcific routine may for example decide to power up the complete device.
+- * If there is no use-case for this function then provide NULL.
+- *
+- * power_off: This function is called by the brcmfmac when the module gets
+- * unloaded. At this point the device can be powered down or otherwise be reset.
+- * So if an actual power_off is not supported but reset is then reset the device
+- * when this function gets called. This can be particularly useful for low power
+- * devices. If there is no use-case for this function (either power-down or
+- * reset) then provide NULL.
+- *
+- * reset: This function can get called if the device communication broke down.
+- * This functionality is particularly useful in case of SDIO type devices. It is
+- * possible to reset a dongle via sdio data interface, but it requires that
+- * this is fully functional. This function is chip/module specific and this
+- * function should return only after the complete reset has completed.
+- */
+-
+-#define BRCMFMAC_SDIO_PDATA_NAME "brcmfmac_sdio"
+-
+-struct brcmfmac_sdio_platform_data {
+- unsigned int drive_strength;
+- bool oob_irq_supported;
+- unsigned int oob_irq_nr;
+- unsigned long oob_irq_flags;
+- bool broken_sg_support;
+- unsigned short sd_head_align;
+- unsigned short sd_sgentry_align;
+- void (*power_on)(void);
+- void (*power_off)(void);
+- void (*reset)(void);
+-};
+-
+-#endif /* _LINUX_BRCMFMAC_PLATFORM_H */
+--- /dev/null
++++ b/include/linux/platform_data/brcmfmac.h
+@@ -0,0 +1,185 @@
++/*
++ * Copyright (c) 201 Broadcom Corporation
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef _LINUX_BRCMFMAC_PLATFORM_H
++#define _LINUX_BRCMFMAC_PLATFORM_H
++
++
++#define BRCMFMAC_PDATA_NAME "brcmfmac"
++
++#define BRCMFMAC_COUNTRY_BUF_SZ 4
++
++
++/*
++ * Platform specific driver functions and data. Through the platform specific
++ * device data functions and data can be provided to help the brcmfmac driver to
++ * operate with the device in combination with the used platform.
++ */
++
++
++/**
++ * Note: the brcmfmac can be loaded as module or be statically built-in into
++ * the kernel. If built-in then do note that it uses module_init (and
++ * module_exit) routines which equal device_initcall. So if you intend to
++ * create a module with the platform specific data for the brcmfmac and have
++ * it built-in to the kernel then use a higher initcall then device_initcall
++ * (see init.h). If this is not done then brcmfmac will load without problems
++ * but will not pickup the platform data.
++ *
++ * When the driver does not "detect" platform driver data then it will continue
++ * without reporting anything and just assume there is no data needed. Which is
++ * probably true for most platforms.
++ */
++
++/**
++ * enum brcmf_bus_type - Bus type identifier. Currently SDIO, USB and PCIE are
++ * supported.
++ */
++enum brcmf_bus_type {
++ BRCMF_BUSTYPE_SDIO,
++ BRCMF_BUSTYPE_USB,
++ BRCMF_BUSTYPE_PCIE
++};
++
++
++/**
++ * struct brcmfmac_sdio_pd - SDIO Device specific platform data.
++ *
++ * @txglomsz: SDIO txglom size. Use 0 if default of driver is to be
++ * used.
++ * @drive_strength: is the preferred drive_strength to be used for the SDIO
++ * pins. If 0 then a default value will be used. This is
++ * the target drive strength, the exact drive strength
++ * which will be used depends on the capabilities of the
++ * device.
++ * @oob_irq_supported: does the board have support for OOB interrupts. SDIO
++ * in-band interrupts are relatively slow and for having
++ * less overhead on interrupt processing an out of band
++ * interrupt can be used. If the HW supports this then
++ * enable this by setting this field to true and configure
++ * the oob related fields.
++ * @oob_irq_nr,
++ * @oob_irq_flags: the OOB interrupt information. The values are used for
++ * registering the irq using request_irq function.
++ * @broken_sg_support: flag for broken sg list support of SDIO host controller.
++ * Set this to true if the SDIO host controller has higher
++ * align requirement than 32 bytes for each scatterlist
++ * item.
++ * @sd_head_align: alignment requirement for start of data buffer.
++ * @sd_sgentry_align: length alignment requirement for each sg entry.
++ * @reset: This function can get called if the device communication
++ * broke down. This functionality is particularly useful in
++ * case of SDIO type devices. It is possible to reset a
++ * dongle via sdio data interface, but it requires that
++ * this is fully functional. This function is chip/module
++ * specific and this function should return only after the
++ * complete reset has completed.
++ */
++struct brcmfmac_sdio_pd {
++ int txglomsz;
++ unsigned int drive_strength;
++ bool oob_irq_supported;
++ unsigned int oob_irq_nr;
++ unsigned long oob_irq_flags;
++ bool broken_sg_support;
++ unsigned short sd_head_align;
++ unsigned short sd_sgentry_align;
++ void (*reset)(void);
++};
++
++/**
++ * struct brcmfmac_pd_cc_entry - Struct for translating user space country code
++ * (iso3166) to firmware country code and
++ * revision.
++ *
++ * @iso3166: iso3166 alpha 2 country code string.
++ * @cc: firmware country code string.
++ * @rev: firmware country code revision.
++ */
++struct brcmfmac_pd_cc_entry {
++ char iso3166[BRCMFMAC_COUNTRY_BUF_SZ];
++ char cc[BRCMFMAC_COUNTRY_BUF_SZ];
++ s32 rev;
++};
++
++/**
++ * struct brcmfmac_pd_cc - Struct for translating country codes as set by user
++ * space to a country code and rev which can be used by
++ * firmware.
++ *
++ * @table_size: number of entries in table (> 0)
++ * @table: array of 1 or more elements with translation information.
++ */
++struct brcmfmac_pd_cc {
++ int table_size;
++ struct brcmfmac_pd_cc_entry table[0];
++};
++
++/**
++ * struct brcmfmac_pd_device - Device specific platform data. (id/rev/bus_type)
++ * is the unique identifier of the device.
++ *
++ * @id: ID of the device for which this data is. In case of SDIO
++ * or PCIE this is the chipid as identified by chip.c In
++ * case of USB this is the chipid as identified by the
++ * device query.
++ * @rev: chip revision, see id.
++ * @bus_type: The type of bus. Some chipid/rev exist for different bus
++ * types. Each bus type has its own set of settings.
++ * @feature_disable: Bitmask of features to disable (override), See feature.c
++ * in brcmfmac for details.
++ * @country_codes: If available, pointer to struct for translating country
++ * codes.
++ * @bus: Bus specific (union) device settings. Currently only
++ * SDIO.
++ */
++struct brcmfmac_pd_device {
++ unsigned int id;
++ unsigned int rev;
++ enum brcmf_bus_type bus_type;
++ unsigned int feature_disable;
++ struct brcmfmac_pd_cc *country_codes;
++ union {
++ struct brcmfmac_sdio_pd sdio;
++ } bus;
++};
++
++/**
++ * struct brcmfmac_platform_data - BRCMFMAC specific platform data.
++ *
++ * @power_on: This function is called by the brcmfmac driver when the module
++ * gets loaded. This can be particularly useful for low power
++ * devices. The platform spcific routine may for example decide to
++ * power up the complete device. If there is no use-case for this
++ * function then provide NULL.
++ * @power_off: This function is called by the brcmfmac when the module gets
++ * unloaded. At this point the devices can be powered down or
++ * otherwise be reset. So if an actual power_off is not supported
++ * but reset is supported by the devices then reset the devices
++ * when this function gets called. This can be particularly useful
++ * for low power devices. If there is no use-case for this
++ * function then provide NULL.
++ */
++struct brcmfmac_platform_data {
++ void (*power_on)(void);
++ void (*power_off)(void);
++ char *fw_alternative_path;
++ int device_count;
++ struct brcmfmac_pd_device devices[0];
++};
++
++
++#endif /* _LINUX_BRCMFMAC_PLATFORM_H */
diff --git a/package/kernel/mac80211/patches/344-0018-brcmfmac-merge-platform-data-and-module-paramaters.patch b/package/kernel/mac80211/patches/344-0018-brcmfmac-merge-platform-data-and-module-paramaters.patch
new file mode 100644
index 0000000000..34341d7f18
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0018-brcmfmac-merge-platform-data-and-module-paramaters.patch
@@ -0,0 +1,607 @@
+From: Hante Meuleman <meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:08 +0100
+Subject: [PATCH] brcmfmac: merge platform data and module paramaters
+
+Merge module parameters and platform data in one struct. This is the
+last step to move to the new platform data per device. Now parameters
+of platform data will be merged with module parameters per device.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -109,8 +109,8 @@ int brcmf_sdiod_intr_register(struct brc
+ u32 addr, gpiocontrol;
+ unsigned long flags;
+
+- pdata = sdiodev->pdata;
+- if ((pdata) && (pdata->oob_irq_supported)) {
++ pdata = &sdiodev->settings->bus.sdio;
++ if (pdata->oob_irq_supported) {
+ brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
+ pdata->oob_irq_nr);
+ ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler,
+@@ -177,8 +177,8 @@ int brcmf_sdiod_intr_unregister(struct b
+
+ brcmf_dbg(SDIO, "Entering\n");
+
+- pdata = sdiodev->pdata;
+- if ((pdata) && (pdata->oob_irq_supported)) {
++ pdata = &sdiodev->settings->bus.sdio;
++ if (pdata->oob_irq_supported) {
+ sdio_claim_host(sdiodev->func[1]);
+ brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
+ brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+@@ -522,7 +522,7 @@ static int brcmf_sdiod_sglist_rw(struct
+ target_list = pktlist;
+ /* for host with broken sg support, prepare a page aligned list */
+ __skb_queue_head_init(&local_list);
+- if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
++ if (!write && sdiodev->settings->bus.sdio.broken_sg_support) {
+ req_sz = 0;
+ skb_queue_walk(pktlist, pkt_next)
+ req_sz += pkt_next->len;
+@@ -629,7 +629,7 @@ static int brcmf_sdiod_sglist_rw(struct
+ }
+ }
+
+- if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
++ if (!write && sdiodev->settings->bus.sdio.broken_sg_support) {
+ local_pkt_next = local_list.next;
+ orig_offset = 0;
+ skb_queue_walk(pktlist, pkt_next) {
+@@ -900,7 +900,7 @@ void brcmf_sdiod_sgtable_alloc(struct br
+ return;
+
+ nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE,
+- sdiodev->bus_if->drvr->settings->sdiod_txglomsz);
++ sdiodev->settings->bus.sdio.txglomsz);
+ nents += (nents >> 4) + 1;
+
+ WARN_ON(nents > sdiodev->max_segment_count);
+@@ -912,7 +912,7 @@ void brcmf_sdiod_sgtable_alloc(struct br
+ sdiodev->sg_support = false;
+ }
+
+- sdiodev->txglomsz = sdiodev->bus_if->drvr->settings->sdiod_txglomsz;
++ sdiodev->txglomsz = sdiodev->settings->bus.sdio.txglomsz;
+ }
+
+ #ifdef CONFIG_PM_SLEEP
+@@ -1246,8 +1246,8 @@ static int brcmf_ops_sdio_suspend(struct
+
+ sdio_flags = MMC_PM_KEEP_POWER;
+ if (sdiodev->wowl_enabled) {
+- if (sdiodev->pdata->oob_irq_supported)
+- enable_irq_wake(sdiodev->pdata->oob_irq_nr);
++ if (sdiodev->settings->bus.sdio.oob_irq_supported)
++ enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
+ else
+ sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+@@ -43,6 +43,8 @@ enum brcmf_bus_protocol_type {
+ BRCMF_PROTO_MSGBUF
+ };
+
++struct brcmf_mp_device;
++
+ struct brcmf_bus_dcmd {
+ char *name;
+ char *param;
+@@ -217,7 +219,7 @@ bool brcmf_c_prec_enq(struct device *dev
+ void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp);
+
+ /* Indication from bus module regarding presence/insertion of dongle. */
+-int brcmf_attach(struct device *dev);
++int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings);
+ /* Indication from bus module regarding removal/absence of dongle */
+ void brcmf_detach(struct device *dev);
+ /* Indication from bus module that dongle should be reset */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+@@ -243,14 +243,35 @@ static void brcmf_mp_attach(void)
+ }
+ }
+
+-struct brcmfmac_sdio_pd *brcmf_get_module_param(struct device *dev,
+- enum brcmf_bus_type bus_type,
+- u32 chip, u32 chiprev)
++struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
++ enum brcmf_bus_type bus_type,
++ u32 chip, u32 chiprev)
+ {
+- struct brcmfmac_sdio_pd *pdata;
++ struct brcmf_mp_device *settings;
+ struct brcmfmac_pd_device *device_pd;
++ bool found;
+ int i;
+
++ brcmf_dbg(INFO, "Enter, bus=%d, chip=%d, rev=%d\n", bus_type, chip,
++ chiprev);
++ settings = kzalloc(sizeof(*settings), GFP_ATOMIC);
++ if (!settings)
++ return NULL;
++
++ /* start by using the module paramaters */
++ settings->p2p_enable = !!brcmf_p2p_enable;
++ settings->feature_disable = brcmf_feature_disable;
++ settings->fcmode = brcmf_fcmode;
++ settings->roamoff = !!brcmf_roamoff;
++#ifdef DEBUG
++ settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
++#endif
++
++ if (bus_type == BRCMF_BUSTYPE_SDIO)
++ settings->bus.sdio.txglomsz = brcmf_sdiod_txglomsz;
++
++ /* See if there is any device specific platform data configured */
++ found = false;
+ if (brcmfmac_pdata) {
+ for (i = 0; i < brcmfmac_pdata->device_count; i++) {
+ device_pd = &brcmfmac_pdata->devices[i];
+@@ -259,38 +280,29 @@ struct brcmfmac_sdio_pd *brcmf_get_modul
+ ((device_pd->rev == chiprev) ||
+ (device_pd->rev == -1))) {
+ brcmf_dbg(INFO, "Platform data for device found\n");
++ settings->country_codes =
++ device_pd->country_codes;
+ if (device_pd->bus_type == BRCMF_BUSTYPE_SDIO)
+- return &device_pd->bus.sdio;
++ memcpy(&settings->bus.sdio,
++ &device_pd->bus.sdio,
++ sizeof(settings->bus.sdio));
++ found = true;
+ break;
+ }
+ }
+ }
+- pdata = NULL;
+- brcmf_of_probe(dev, &pdata);
+-
+- return pdata;
+-}
+-
+-int brcmf_mp_device_attach(struct brcmf_pub *drvr)
+-{
+- drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC);
+- if (!drvr->settings)
+- return -ENOMEM;
+-
+- drvr->settings->sdiod_txglomsz = brcmf_sdiod_txglomsz;
+- drvr->settings->p2p_enable = !!brcmf_p2p_enable;
+- drvr->settings->feature_disable = brcmf_feature_disable;
+- drvr->settings->fcmode = brcmf_fcmode;
+- drvr->settings->roamoff = !!brcmf_roamoff;
+-#ifdef DEBUG
+- drvr->settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
+-#endif
+- return 0;
++ if ((bus_type == BRCMF_BUSTYPE_SDIO) && (!found)) {
++ /* No platform data for this device. In case of SDIO try OF
++ * (Open Firwmare) Device Tree.
++ */
++ brcmf_of_probe(dev, &settings->bus.sdio);
++ }
++ return settings;
+ }
+
+-void brcmf_mp_device_detach(struct brcmf_pub *drvr)
++void brcmf_release_module_param(struct brcmf_mp_device *module_param)
+ {
+- kfree(drvr->settings);
++ kfree(module_param);
+ }
+
+ static int __init brcmf_common_pd_probe(struct platform_device *pdev)
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+@@ -45,41 +45,30 @@ extern struct brcmf_mp_global_t brcmf_mp
+ /**
+ * struct brcmf_mp_device - Device module paramaters.
+ *
+- * @sdiod_txglomsz: SDIO txglom size.
+- * @joinboost_5g_rssi: 5g rssi booost for preferred join selection.
+ * @p2p_enable: Legacy P2P0 enable (old wpa_supplicant).
+ * @feature_disable: Feature_disable bitmask.
+ * @fcmode: FWS flow control.
+ * @roamoff: Firmware roaming off?
++ * @ignore_probe_fail: Ignore probe failure.
+ * @country_codes: If available, pointer to struct for translating country codes
++ * @bus: Bus specific platform data. Only SDIO at the mmoment.
+ */
+ struct brcmf_mp_device {
+- int sdiod_txglomsz;
+- int joinboost_5g_rssi;
+- bool p2p_enable;
+- int feature_disable;
+- int fcmode;
+- bool roamoff;
+- bool ignore_probe_fail;
++ bool p2p_enable;
++ unsigned int feature_disable;
++ int fcmode;
++ bool roamoff;
++ bool ignore_probe_fail;
+ struct brcmfmac_pd_cc *country_codes;
++ union {
++ struct brcmfmac_sdio_pd sdio;
++ } bus;
+ };
+
+-struct brcmfmac_sdio_pd *brcmf_get_module_param(struct device *dev,
+- enum brcmf_bus_type bus_type,
+- u32 chip, u32 chiprev);
+-int brcmf_mp_device_attach(struct brcmf_pub *drvr);
+-void brcmf_mp_device_detach(struct brcmf_pub *drvr);
+-#ifdef DEBUG
+-static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr)
+-{
+- return drvr->settings->ignore_probe_fail;
+-}
+-#else
+-static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr)
+-{
+- return false;
+-}
+-#endif
++struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
++ enum brcmf_bus_type bus_type,
++ u32 chip, u32 chiprev);
++void brcmf_release_module_param(struct brcmf_mp_device *module_param);
+
+ /* Sets dongle media info (drv_version, mac address). */
+ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1104,7 +1104,7 @@ static int brcmf_inet6addr_changed(struc
+ }
+ #endif
+
+-int brcmf_attach(struct device *dev)
++int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
+ {
+ struct brcmf_pub *drvr = NULL;
+ int ret = 0;
+@@ -1126,10 +1126,7 @@ int brcmf_attach(struct device *dev)
+ drvr->hdrlen = 0;
+ drvr->bus_if = dev_get_drvdata(dev);
+ drvr->bus_if->drvr = drvr;
+-
+- /* Initialize device specific settings */
+- if (brcmf_mp_device_attach(drvr))
+- goto fail;
++ drvr->settings = settings;
+
+ /* attach debug facilities */
+ brcmf_debug_attach(drvr);
+@@ -1274,7 +1271,7 @@ fail:
+ brcmf_net_detach(p2p_ifp->ndev);
+ drvr->iflist[0] = NULL;
+ drvr->iflist[1] = NULL;
+- if (brcmf_ignoring_probe_fail(drvr))
++ if (drvr->settings->ignore_probe_fail)
+ ret = 0;
+
+ return ret;
+@@ -1350,8 +1347,6 @@ void brcmf_detach(struct device *dev)
+
+ brcmf_proto_detach(drvr);
+
+- brcmf_mp_device_detach(drvr);
+-
+ brcmf_debug_detach(drvr);
+ bus_if->drvr = NULL;
+ kfree(drvr);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+@@ -23,7 +23,7 @@
+ #include "common.h"
+ #include "of.h"
+
+-void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
++void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
+ {
+ struct device_node *np = dev->of_node;
+ int irq;
+@@ -33,12 +33,8 @@ void brcmf_of_probe(struct device *dev,
+ if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
+ return;
+
+- *sdio = devm_kzalloc(dev, sizeof(*sdio), GFP_KERNEL);
+- if (!(*sdio))
+- return;
+-
+ if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
+- (*sdio)->drive_strength = val;
++ sdio->drive_strength = val;
+
+ /* make sure there are interrupts defined in the node */
+ if (!of_find_property(np, "interrupts", NULL))
+@@ -51,7 +47,7 @@ void brcmf_of_probe(struct device *dev,
+ }
+ irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
+
+- (*sdio)->oob_irq_supported = true;
+- (*sdio)->oob_irq_nr = irq;
+- (*sdio)->oob_irq_flags = irqf;
++ sdio->oob_irq_supported = true;
++ sdio->oob_irq_nr = irq;
++ sdio->oob_irq_flags = irqf;
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
+@@ -14,10 +14,9 @@
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+ #ifdef CONFIG_OF
+-void
+-brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio);
++void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio);
+ #else
+-static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
++static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
+ {
+ }
+ #endif /* CONFIG_OF */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -37,6 +37,8 @@
+ #include "pcie.h"
+ #include "firmware.h"
+ #include "chip.h"
++#include "core.h"
++#include "common.h"
+
+
+ enum brcmf_pcie_state {
+@@ -266,6 +268,7 @@ struct brcmf_pciedev_info {
+ u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
+ void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+ u16 value);
++ struct brcmf_mp_device *settings;
+ };
+
+ struct brcmf_pcie_ringbuf {
+@@ -1525,16 +1528,16 @@ static void brcmf_pcie_release_resource(
+ }
+
+
+-static int brcmf_pcie_attach_bus(struct device *dev)
++static int brcmf_pcie_attach_bus(struct brcmf_pciedev_info *devinfo)
+ {
+ int ret;
+
+ /* Attach to the common driver interface */
+- ret = brcmf_attach(dev);
++ ret = brcmf_attach(&devinfo->pdev->dev, devinfo->settings);
+ if (ret) {
+ brcmf_err("brcmf_attach failed\n");
+ } else {
+- ret = brcmf_bus_start(dev);
++ ret = brcmf_bus_start(&devinfo->pdev->dev);
+ if (ret)
+ brcmf_err("dongle is not responding\n");
+ }
+@@ -1672,7 +1675,7 @@ static void brcmf_pcie_setup(struct devi
+ init_waitqueue_head(&devinfo->mbdata_resp_wait);
+
+ brcmf_pcie_intr_enable(devinfo);
+- if (brcmf_pcie_attach_bus(bus->dev) == 0)
++ if (brcmf_pcie_attach_bus(devinfo) == 0)
+ return;
+
+ brcmf_pcie_bus_console_read(devinfo);
+@@ -1716,6 +1719,15 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
+ goto fail;
+ }
+
++ devinfo->settings = brcmf_get_module_param(&devinfo->pdev->dev,
++ BRCMF_BUSTYPE_PCIE,
++ devinfo->ci->chip,
++ devinfo->ci->chiprev);
++ if (!devinfo->settings) {
++ ret = -ENOMEM;
++ goto fail;
++ }
++
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+ if (!bus) {
+ ret = -ENOMEM;
+@@ -1760,6 +1772,8 @@ fail:
+ brcmf_pcie_release_resource(devinfo);
+ if (devinfo->ci)
+ brcmf_chip_detach(devinfo->ci);
++ if (devinfo->settings)
++ brcmf_release_module_param(devinfo->settings);
+ kfree(pcie_bus_dev);
+ kfree(devinfo);
+ return ret;
+@@ -1799,6 +1813,8 @@ brcmf_pcie_remove(struct pci_dev *pdev)
+
+ if (devinfo->ci)
+ brcmf_chip_detach(devinfo->ci);
++ if (devinfo->settings)
++ brcmf_release_module_param(devinfo->settings);
+
+ kfree(devinfo);
+ dev_set_drvdata(&pdev->dev, NULL);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -2442,15 +2442,17 @@ static void brcmf_sdio_bus_stop(struct d
+
+ static inline void brcmf_sdio_clrintr(struct brcmf_sdio *bus)
+ {
++ struct brcmf_sdio_dev *sdiodev;
+ unsigned long flags;
+
+- if (bus->sdiodev->oob_irq_requested) {
+- spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
+- if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
+- enable_irq(bus->sdiodev->pdata->oob_irq_nr);
+- bus->sdiodev->irq_en = true;
++ sdiodev = bus->sdiodev;
++ if (sdiodev->oob_irq_requested) {
++ spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
++ if (!sdiodev->irq_en && !atomic_read(&bus->ipend)) {
++ enable_irq(sdiodev->settings->bus.sdio.oob_irq_nr);
++ sdiodev->irq_en = true;
+ }
+- spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
++ spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
+ }
+ }
+
+@@ -3394,9 +3396,7 @@ static int brcmf_sdio_bus_preinit(struct
+ sizeof(u32));
+ } else {
+ /* otherwise, set txglomalign */
+- value = 4;
+- if (sdiodev->pdata)
+- value = sdiodev->pdata->sd_sgentry_align;
++ value = sdiodev->settings->bus.sdio.sd_sgentry_align;
+ /* SDIO ADMA requires at least 32 bit alignment */
+ value = max_t(u32, value, 4);
+ err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,
+@@ -3811,21 +3811,25 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+ bus->ci = NULL;
+ goto fail;
+ }
+- sdiodev->pdata = brcmf_get_module_param(sdiodev->dev,
++ sdiodev->settings = brcmf_get_module_param(sdiodev->dev,
+ BRCMF_BUSTYPE_SDIO,
+ bus->ci->chip,
+ bus->ci->chiprev);
++ if (!sdiodev->settings) {
++ brcmf_err("Failed to get device parameters\n");
++ goto fail;
++ }
+ /* platform specific configuration:
+ * alignments must be at least 4 bytes for ADMA
+ */
+ bus->head_align = ALIGNMENT;
+ bus->sgentry_align = ALIGNMENT;
+- if (sdiodev->pdata) {
+- if (sdiodev->pdata->sd_head_align > ALIGNMENT)
+- bus->head_align = sdiodev->pdata->sd_head_align;
+- if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT)
+- bus->sgentry_align = sdiodev->pdata->sd_sgentry_align;
+- }
++ if (sdiodev->settings->bus.sdio.sd_head_align > ALIGNMENT)
++ bus->head_align = sdiodev->settings->bus.sdio.sd_head_align;
++ if (sdiodev->settings->bus.sdio.sd_sgentry_align > ALIGNMENT)
++ bus->sgentry_align =
++ sdiodev->settings->bus.sdio.sd_sgentry_align;
++
+ /* allocate scatter-gather table. sg support
+ * will be disabled upon allocation failure.
+ */
+@@ -3837,7 +3841,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+ */
+ if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
+ ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
+- (sdiodev->pdata && sdiodev->pdata->oob_irq_supported)))
++ (sdiodev->settings->bus.sdio.oob_irq_supported)))
+ sdiodev->bus_if->wowl_supported = true;
+ #endif
+
+@@ -3846,8 +3850,8 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+ goto fail;
+ }
+
+- if ((sdiodev->pdata) && (sdiodev->pdata->drive_strength))
+- drivestrength = sdiodev->pdata->drive_strength;
++ if (sdiodev->settings->bus.sdio.drive_strength)
++ drivestrength = sdiodev->settings->bus.sdio.drive_strength;
+ else
+ drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
+ brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength);
+@@ -4124,7 +4128,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
+ bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
+
+ /* Attach to the common layer, reserve hdr space */
+- ret = brcmf_attach(bus->sdiodev->dev);
++ ret = brcmf_attach(bus->sdiodev->dev, bus->sdiodev->settings);
+ if (ret != 0) {
+ brcmf_err("brcmf_attach failed\n");
+ goto fail;
+@@ -4228,6 +4232,8 @@ void brcmf_sdio_remove(struct brcmf_sdio
+ }
+ brcmf_chip_detach(bus->ci);
+ }
++ if (bus->sdiodev->settings)
++ brcmf_release_module_param(bus->sdiodev->settings);
+
+ kfree(bus->rxbuf);
+ kfree(bus->hdrbuf);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+@@ -184,7 +184,7 @@ struct brcmf_sdio_dev {
+ struct brcmf_sdio *bus;
+ struct device *dev;
+ struct brcmf_bus *bus_if;
+- struct brcmfmac_sdio_pd *pdata;
++ struct brcmf_mp_device *settings;
+ bool oob_irq_requested;
+ bool irq_en; /* irq enable flags */
+ spinlock_t irq_en_lock;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+@@ -27,6 +27,8 @@
+ #include "debug.h"
+ #include "firmware.h"
+ #include "usb.h"
++#include "core.h"
++#include "common.h"
+
+
+ #define IOCTL_RESP_TIMEOUT msecs_to_jiffies(2000)
+@@ -171,6 +173,7 @@ struct brcmf_usbdev_info {
+ struct urb *bulk_urb; /* used for FW download */
+
+ bool wowl_enabled;
++ struct brcmf_mp_device *settings;
+ };
+
+ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
+@@ -1027,6 +1030,9 @@ static void brcmf_usb_detach(struct brcm
+
+ kfree(devinfo->tx_reqs);
+ kfree(devinfo->rx_reqs);
++
++ if (devinfo->settings)
++ brcmf_release_module_param(devinfo->settings);
+ }
+
+
+@@ -1136,7 +1142,7 @@ static int brcmf_usb_bus_setup(struct br
+ int ret;
+
+ /* Attach to the common driver interface */
+- ret = brcmf_attach(devinfo->dev);
++ ret = brcmf_attach(devinfo->dev, devinfo->settings);
+ if (ret) {
+ brcmf_err("brcmf_attach failed\n");
+ return ret;
+@@ -1223,6 +1229,14 @@ static int brcmf_usb_probe_cb(struct brc
+ bus->wowl_supported = true;
+ #endif
+
++ devinfo->settings = brcmf_get_module_param(bus->dev, BRCMF_BUSTYPE_USB,
++ bus_pub->devid,
++ bus_pub->chiprev);
++ if (!devinfo->settings) {
++ ret = -ENOMEM;
++ goto fail;
++ }
++
+ if (!brcmf_usb_dlneeded(devinfo)) {
+ ret = brcmf_usb_bus_setup(devinfo);
+ if (ret)
diff --git a/package/kernel/mac80211/patches/344-0019-brcmfmac-integrate-add_keyext-in-add_key.patch b/package/kernel/mac80211/patches/344-0019-brcmfmac-integrate-add_keyext-in-add_key.patch
new file mode 100644
index 0000000000..eb680fccfc
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0019-brcmfmac-integrate-add_keyext-in-add_key.patch
@@ -0,0 +1,227 @@
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:09 +0100
+Subject: [PATCH] brcmfmac: integrate add_keyext in add_key
+
+brcmf_add_keyext is called when a key is configured for a specific
+mac address. This function is very similar to the calling function
+brcmf_add_key. Integrate this function and also use existing del_key
+function in case key is to be cleared.
+
+Reviewed-by: Arend Van Spriel <arend.van@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <franky.lin@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -2073,84 +2073,34 @@ done:
+ }
+
+ static s32
+-brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
+- u8 key_idx, const u8 *mac_addr, struct key_params *params)
++brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
++ u8 key_idx, bool pairwise, const u8 *mac_addr)
+ {
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_wsec_key key;
+ s32 err = 0;
+- u8 keybuf[8];
++
++ brcmf_dbg(TRACE, "Enter\n");
++ if (!check_vif_up(ifp->vif))
++ return -EIO;
++
++ if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
++ /* we ignore this key index in this case */
++ return -EINVAL;
++ }
+
+ memset(&key, 0, sizeof(key));
+- key.index = (u32) key_idx;
+- /* Instead of bcast for ea address for default wep keys,
+- driver needs it to be Null */
+- if (!is_multicast_ether_addr(mac_addr))
+- memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
+- key.len = (u32) params->key_len;
+- /* check for key index change */
+- if (key.len == 0) {
+- /* key delete */
+- err = send_key_to_dongle(ifp, &key);
+- if (err)
+- brcmf_err("key delete error (%d)\n", err);
+- } else {
+- if (key.len > sizeof(key.data)) {
+- brcmf_err("Invalid key length (%d)\n", key.len);
+- return -EINVAL;
+- }
+
+- brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
+- memcpy(key.data, params->key, key.len);
++ key.index = (u32)key_idx;
++ key.flags = BRCMF_PRIMARY_KEY;
++ key.algo = CRYPTO_ALGO_OFF;
+
+- if (!brcmf_is_apmode(ifp->vif) &&
+- (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
+- brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
+- memcpy(keybuf, &key.data[24], sizeof(keybuf));
+- memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
+- memcpy(&key.data[16], keybuf, sizeof(keybuf));
+- }
++ brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+
+- /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
+- if (params->seq && params->seq_len == 6) {
+- /* rx iv */
+- u8 *ivptr;
+- ivptr = (u8 *) params->seq;
+- key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
+- (ivptr[3] << 8) | ivptr[2];
+- key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
+- key.iv_initialized = true;
+- }
++ /* Set the new key/index */
++ err = send_key_to_dongle(ifp, &key);
+
+- switch (params->cipher) {
+- case WLAN_CIPHER_SUITE_WEP40:
+- key.algo = CRYPTO_ALGO_WEP1;
+- brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
+- break;
+- case WLAN_CIPHER_SUITE_WEP104:
+- key.algo = CRYPTO_ALGO_WEP128;
+- brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
+- break;
+- case WLAN_CIPHER_SUITE_TKIP:
+- key.algo = CRYPTO_ALGO_TKIP;
+- brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
+- break;
+- case WLAN_CIPHER_SUITE_AES_CMAC:
+- key.algo = CRYPTO_ALGO_AES_CCM;
+- brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
+- break;
+- case WLAN_CIPHER_SUITE_CCMP:
+- key.algo = CRYPTO_ALGO_AES_CCM;
+- brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
+- break;
+- default:
+- brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
+- return -EINVAL;
+- }
+- err = send_key_to_dongle(ifp, &key);
+- if (err)
+- brcmf_err("wsec_key error (%d)\n", err);
+- }
++ brcmf_dbg(TRACE, "Exit\n");
+ return err;
+ }
+
+@@ -2163,8 +2113,9 @@ brcmf_cfg80211_add_key(struct wiphy *wip
+ struct brcmf_wsec_key *key;
+ s32 val;
+ s32 wsec;
+- s32 err = 0;
++ s32 err;
+ u8 keybuf[8];
++ bool ext_key;
+
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+@@ -2177,27 +2128,32 @@ brcmf_cfg80211_add_key(struct wiphy *wip
+ return -EINVAL;
+ }
+
+- if (mac_addr &&
+- (params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
+- (params->cipher != WLAN_CIPHER_SUITE_WEP104)) {
+- brcmf_dbg(TRACE, "Exit");
+- return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
+- }
+-
+- key = &ifp->vif->profile.key[key_idx];
+- memset(key, 0, sizeof(*key));
++ if (params->key_len == 0)
++ return brcmf_cfg80211_del_key(wiphy, ndev, key_idx, pairwise,
++ mac_addr);
+
+ if (params->key_len > sizeof(key->data)) {
+ brcmf_err("Too long key length (%u)\n", params->key_len);
+- err = -EINVAL;
+- goto done;
++ return -EINVAL;
++ }
++
++ ext_key = false;
++ if (mac_addr && (params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
++ (params->cipher != WLAN_CIPHER_SUITE_WEP104)) {
++ brcmf_dbg(TRACE, "Ext key, mac %pM", mac_addr);
++ ext_key = true;
+ }
++
++ key = &ifp->vif->profile.key[key_idx];
++ memset(key, 0, sizeof(*key));
++ if ((ext_key) && (!is_multicast_ether_addr(mac_addr)))
++ memcpy((char *)&key->ea, (void *)mac_addr, ETH_ALEN);
+ key->len = params->key_len;
+ key->index = key_idx;
+-
+ memcpy(key->data, params->key, key->len);
++ if (!ext_key)
++ key->flags = BRCMF_PRIMARY_KEY;
+
+- key->flags = BRCMF_PRIMARY_KEY;
+ switch (params->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ key->algo = CRYPTO_ALGO_WEP1;
+@@ -2237,7 +2193,7 @@ brcmf_cfg80211_add_key(struct wiphy *wip
+ }
+
+ err = send_key_to_dongle(ifp, key);
+- if (err)
++ if (ext_key || err)
+ goto done;
+
+ err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
+@@ -2256,38 +2212,6 @@ done:
+ brcmf_dbg(TRACE, "Exit\n");
+ return err;
+ }
+-
+-static s32
+-brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
+- u8 key_idx, bool pairwise, const u8 *mac_addr)
+-{
+- struct brcmf_if *ifp = netdev_priv(ndev);
+- struct brcmf_wsec_key key;
+- s32 err = 0;
+-
+- brcmf_dbg(TRACE, "Enter\n");
+- if (!check_vif_up(ifp->vif))
+- return -EIO;
+-
+- if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
+- /* we ignore this key index in this case */
+- return -EINVAL;
+- }
+-
+- memset(&key, 0, sizeof(key));
+-
+- key.index = (u32) key_idx;
+- key.flags = BRCMF_PRIMARY_KEY;
+- key.algo = CRYPTO_ALGO_OFF;
+-
+- brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+-
+- /* Set the new key/index */
+- err = send_key_to_dongle(ifp, &key);
+-
+- brcmf_dbg(TRACE, "Exit\n");
+- return err;
+-}
+
+ static s32
+ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
diff --git a/package/kernel/mac80211/patches/344-0020-brcmfmac-add-802.11w-management-frame-protection-sup.patch b/package/kernel/mac80211/patches/344-0020-brcmfmac-add-802.11w-management-frame-protection-sup.patch
new file mode 100644
index 0000000000..c20d40c049
--- /dev/null
+++ b/package/kernel/mac80211/patches/344-0020-brcmfmac-add-802.11w-management-frame-protection-sup.patch
@@ -0,0 +1,509 @@
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Wed, 17 Feb 2016 11:27:10 +0100
+Subject: [PATCH] brcmfmac: add 802.11w management frame protection support
+
+Add full support for both AP and STA for management frame protection.
+
+Reviewed-by: Arend Van Spriel <arend.van@broadcom.com>
+Reviewed-by: Franky (Zhenhui) Lin <franky.lin@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -72,8 +72,13 @@
+ #define RSN_AKM_NONE 0 /* None (IBSS) */
+ #define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */
+ #define RSN_AKM_PSK 2 /* Pre-shared Key */
++#define RSN_AKM_SHA256_1X 5 /* SHA256, 802.1X */
++#define RSN_AKM_SHA256_PSK 6 /* SHA256, Pre-shared Key */
+ #define RSN_CAP_LEN 2 /* Length of RSN capabilities */
+-#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C
++#define RSN_CAP_PTK_REPLAY_CNTR_MASK (BIT(2) | BIT(3))
++#define RSN_CAP_MFPR_MASK BIT(6)
++#define RSN_CAP_MFPC_MASK BIT(7)
++#define RSN_PMKID_COUNT_LEN 2
+
+ #define VNDR_IE_CMD_LEN 4 /* length of the set command
+ * string :"add", "del" (+ NUL)
+@@ -211,12 +216,19 @@ static const struct ieee80211_regdomain
+ REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), }
+ };
+
+-static const u32 __wl_cipher_suites[] = {
++/* Note: brcmf_cipher_suites is an array of int defining which cipher suites
++ * are supported. A pointer to this array and the number of entries is passed
++ * on to upper layers. AES_CMAC defines whether or not the driver supports MFP.
++ * So the cipher suite AES_CMAC has to be the last one in the array, and when
++ * device does not support MFP then the number of suites will be decreased by 1
++ */
++static const u32 brcmf_cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+- WLAN_CIPHER_SUITE_AES_CMAC,
++ /* Keep as last entry: */
++ WLAN_CIPHER_SUITE_AES_CMAC
+ };
+
+ /* Vendor specific ie. id = 221, oui and type defines exact ie */
+@@ -1533,7 +1545,7 @@ static s32 brcmf_set_auth_type(struct ne
+
+ static s32
+ brcmf_set_wsec_mode(struct net_device *ndev,
+- struct cfg80211_connect_params *sme, bool mfp)
++ struct cfg80211_connect_params *sme)
+ {
+ struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+ struct brcmf_cfg80211_security *sec;
+@@ -1592,10 +1604,7 @@ brcmf_set_wsec_mode(struct net_device *n
+ sme->privacy)
+ pval = AES_ENABLED;
+
+- if (mfp)
+- wsec = pval | gval | MFP_CAPABLE;
+- else
+- wsec = pval | gval;
++ wsec = pval | gval;
+ err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", wsec);
+ if (err) {
+ brcmf_err("error (%d)\n", err);
+@@ -1612,56 +1621,100 @@ brcmf_set_wsec_mode(struct net_device *n
+ static s32
+ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
+ {
+- struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+- struct brcmf_cfg80211_security *sec;
+- s32 val = 0;
+- s32 err = 0;
++ struct brcmf_if *ifp = netdev_priv(ndev);
++ s32 val;
++ s32 err;
++ const struct brcmf_tlv *rsn_ie;
++ const u8 *ie;
++ u32 ie_len;
++ u32 offset;
++ u16 rsn_cap;
++ u32 mfp;
++ u16 count;
+
+- if (sme->crypto.n_akm_suites) {
+- err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev),
+- "wpa_auth", &val);
+- if (err) {
+- brcmf_err("could not get wpa_auth (%d)\n", err);
+- return err;
++ if (!sme->crypto.n_akm_suites)
++ return 0;
++
++ err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "wpa_auth", &val);
++ if (err) {
++ brcmf_err("could not get wpa_auth (%d)\n", err);
++ return err;
++ }
++ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
++ switch (sme->crypto.akm_suites[0]) {
++ case WLAN_AKM_SUITE_8021X:
++ val = WPA_AUTH_UNSPECIFIED;
++ break;
++ case WLAN_AKM_SUITE_PSK:
++ val = WPA_AUTH_PSK;
++ break;
++ default:
++ brcmf_err("invalid cipher group (%d)\n",
++ sme->crypto.cipher_group);
++ return -EINVAL;
+ }
+- if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+- switch (sme->crypto.akm_suites[0]) {
+- case WLAN_AKM_SUITE_8021X:
+- val = WPA_AUTH_UNSPECIFIED;
+- break;
+- case WLAN_AKM_SUITE_PSK:
+- val = WPA_AUTH_PSK;
+- break;
+- default:
+- brcmf_err("invalid cipher group (%d)\n",
+- sme->crypto.cipher_group);
+- return -EINVAL;
+- }
+- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+- switch (sme->crypto.akm_suites[0]) {
+- case WLAN_AKM_SUITE_8021X:
+- val = WPA2_AUTH_UNSPECIFIED;
+- break;
+- case WLAN_AKM_SUITE_PSK:
+- val = WPA2_AUTH_PSK;
+- break;
+- default:
+- brcmf_err("invalid cipher group (%d)\n",
+- sme->crypto.cipher_group);
+- return -EINVAL;
+- }
++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
++ switch (sme->crypto.akm_suites[0]) {
++ case WLAN_AKM_SUITE_8021X:
++ val = WPA2_AUTH_UNSPECIFIED;
++ break;
++ case WLAN_AKM_SUITE_8021X_SHA256:
++ val = WPA2_AUTH_1X_SHA256;
++ break;
++ case WLAN_AKM_SUITE_PSK_SHA256:
++ val = WPA2_AUTH_PSK_SHA256;
++ break;
++ case WLAN_AKM_SUITE_PSK:
++ val = WPA2_AUTH_PSK;
++ break;
++ default:
++ brcmf_err("invalid cipher group (%d)\n",
++ sme->crypto.cipher_group);
++ return -EINVAL;
+ }
++ }
+
+- brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
+- err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev),
+- "wpa_auth", val);
+- if (err) {
+- brcmf_err("could not set wpa_auth (%d)\n", err);
+- return err;
+- }
++ if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
++ goto skip_mfp_config;
++ /* The MFP mode (1 or 2) needs to be determined, parse IEs. The
++ * IE will not be verified, just a quick search for MFP config
++ */
++ rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie, sme->ie_len,
++ WLAN_EID_RSN);
++ if (!rsn_ie)
++ goto skip_mfp_config;
++ ie = (const u8 *)rsn_ie;
++ ie_len = rsn_ie->len + TLV_HDR_LEN;
++ /* Skip unicast suite */
++ offset = TLV_HDR_LEN + WPA_IE_VERSION_LEN + WPA_IE_MIN_OUI_LEN;
++ if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
++ goto skip_mfp_config;
++ /* Skip multicast suite */
++ count = ie[offset] + (ie[offset + 1] << 8);
++ offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
++ if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
++ goto skip_mfp_config;
++ /* Skip auth key management suite(s) */
++ count = ie[offset] + (ie[offset + 1] << 8);
++ offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
++ if (offset + WPA_IE_SUITE_COUNT_LEN > ie_len)
++ goto skip_mfp_config;
++ /* Ready to read capabilities */
++ mfp = BRCMF_MFP_NONE;
++ rsn_cap = ie[offset] + (ie[offset + 1] << 8);
++ if (rsn_cap & RSN_CAP_MFPR_MASK)
++ mfp = BRCMF_MFP_REQUIRED;
++ else if (rsn_cap & RSN_CAP_MFPC_MASK)
++ mfp = BRCMF_MFP_CAPABLE;
++ brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
++
++skip_mfp_config:
++ brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
++ err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
++ if (err) {
++ brcmf_err("could not set wpa_auth (%d)\n", err);
++ return err;
+ }
+- sec = &profile->sec;
+- sec->wpa_auth = sme->crypto.akm_suites[0];
+
+ return err;
+ }
+@@ -1827,7 +1880,7 @@ brcmf_cfg80211_connect(struct wiphy *wip
+ goto done;
+ }
+
+- err = brcmf_set_wsec_mode(ndev, sme, sme->mfp == NL80211_MFP_REQUIRED);
++ err = brcmf_set_wsec_mode(ndev, sme);
+ if (err) {
+ brcmf_err("wl_set_set_cipher failed (%d)\n", err);
+ goto done;
+@@ -2077,10 +2130,12 @@ brcmf_cfg80211_del_key(struct wiphy *wip
+ u8 key_idx, bool pairwise, const u8 *mac_addr)
+ {
+ struct brcmf_if *ifp = netdev_priv(ndev);
+- struct brcmf_wsec_key key;
+- s32 err = 0;
++ struct brcmf_wsec_key *key;
++ s32 err;
+
+ brcmf_dbg(TRACE, "Enter\n");
++ brcmf_dbg(CONN, "key index (%d)\n", key_idx);
++
+ if (!check_vif_up(ifp->vif))
+ return -EIO;
+
+@@ -2089,16 +2144,19 @@ brcmf_cfg80211_del_key(struct wiphy *wip
+ return -EINVAL;
+ }
+
+- memset(&key, 0, sizeof(key));
++ key = &ifp->vif->profile.key[key_idx];
+
+- key.index = (u32)key_idx;
+- key.flags = BRCMF_PRIMARY_KEY;
+- key.algo = CRYPTO_ALGO_OFF;
++ if (key->algo == CRYPTO_ALGO_OFF) {
++ brcmf_dbg(CONN, "Ignore clearing of (never configured) key\n");
++ return -EINVAL;
++ }
+
+- brcmf_dbg(CONN, "key index (%d)\n", key_idx);
++ memset(key, 0, sizeof(*key));
++ key->index = (u32)key_idx;
++ key->flags = BRCMF_PRIMARY_KEY;
+
+- /* Set the new key/index */
+- err = send_key_to_dongle(ifp, &key);
++ /* Clear the key/index */
++ err = send_key_to_dongle(ifp, key);
+
+ brcmf_dbg(TRACE, "Exit\n");
+ return err;
+@@ -2106,8 +2164,8 @@ brcmf_cfg80211_del_key(struct wiphy *wip
+
+ static s32
+ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
+- u8 key_idx, bool pairwise, const u8 *mac_addr,
+- struct key_params *params)
++ u8 key_idx, bool pairwise, const u8 *mac_addr,
++ struct key_params *params)
+ {
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct brcmf_wsec_key *key;
+@@ -2214,9 +2272,10 @@ done:
+ }
+
+ static s32
+-brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
+- u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
+- void (*callback) (void *cookie, struct key_params * params))
++brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx,
++ bool pairwise, const u8 *mac_addr, void *cookie,
++ void (*callback)(void *cookie,
++ struct key_params *params))
+ {
+ struct key_params params;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+@@ -2268,8 +2327,15 @@ done:
+
+ static s32
+ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+- struct net_device *ndev, u8 key_idx)
++ struct net_device *ndev, u8 key_idx)
+ {
++ struct brcmf_if *ifp = netdev_priv(ndev);
++
++ brcmf_dbg(TRACE, "Enter key_idx %d\n", key_idx);
++
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
++ return 0;
++
+ brcmf_dbg(INFO, "Not supported\n");
+
+ return -EOPNOTSUPP;
+@@ -3769,7 +3835,7 @@ brcmf_configure_wpaie(struct brcmf_if *i
+ u32 auth = 0; /* d11 open authentication */
+ u16 count;
+ s32 err = 0;
+- s32 len = 0;
++ s32 len;
+ u32 i;
+ u32 wsec;
+ u32 pval = 0;
+@@ -3779,6 +3845,7 @@ brcmf_configure_wpaie(struct brcmf_if *i
+ u8 *data;
+ u16 rsn_cap;
+ u32 wme_bss_disable;
++ u32 mfp;
+
+ brcmf_dbg(TRACE, "Enter\n");
+ if (wpa_ie == NULL)
+@@ -3893,19 +3960,53 @@ brcmf_configure_wpaie(struct brcmf_if *i
+ is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
+ (wpa_auth |= WPA_AUTH_PSK);
+ break;
++ case RSN_AKM_SHA256_PSK:
++ brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n");
++ wpa_auth |= WPA2_AUTH_PSK_SHA256;
++ break;
++ case RSN_AKM_SHA256_1X:
++ brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n");
++ wpa_auth |= WPA2_AUTH_1X_SHA256;
++ break;
+ default:
+ brcmf_err("Ivalid key mgmt info\n");
+ }
+ offset++;
+ }
+
++ mfp = BRCMF_MFP_NONE;
+ if (is_rsn_ie) {
+ wme_bss_disable = 1;
+ if ((offset + RSN_CAP_LEN) <= len) {
+ rsn_cap = data[offset] + (data[offset + 1] << 8);
+ if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK)
+ wme_bss_disable = 0;
++ if (rsn_cap & RSN_CAP_MFPR_MASK) {
++ brcmf_dbg(TRACE, "MFP Required\n");
++ mfp = BRCMF_MFP_REQUIRED;
++ /* Firmware only supports mfp required in
++ * combination with WPA2_AUTH_PSK_SHA256 or
++ * WPA2_AUTH_1X_SHA256.
++ */
++ if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 |
++ WPA2_AUTH_1X_SHA256))) {
++ err = -EINVAL;
++ goto exit;
++ }
++ /* Firmware has requirement that WPA2_AUTH_PSK/
++ * WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI
++ * is to be included in the rsn ie.
++ */
++ if (wpa_auth & WPA2_AUTH_PSK_SHA256)
++ wpa_auth |= WPA2_AUTH_PSK;
++ else if (wpa_auth & WPA2_AUTH_1X_SHA256)
++ wpa_auth |= WPA2_AUTH_UNSPECIFIED;
++ } else if (rsn_cap & RSN_CAP_MFPC_MASK) {
++ brcmf_dbg(TRACE, "MFP Capable\n");
++ mfp = BRCMF_MFP_CAPABLE;
++ }
+ }
++ offset += RSN_CAP_LEN;
+ /* set wme_bss_disable to sync RSN Capabilities */
+ err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",
+ wme_bss_disable);
+@@ -3913,6 +4014,21 @@ brcmf_configure_wpaie(struct brcmf_if *i
+ brcmf_err("wme_bss_disable error %d\n", err);
+ goto exit;
+ }
++
++ /* Skip PMKID cnt as it is know to be 0 for AP. */
++ offset += RSN_PMKID_COUNT_LEN;
++
++ /* See if there is BIP wpa suite left for MFP */
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP) &&
++ ((offset + WPA_IE_MIN_OUI_LEN) <= len)) {
++ err = brcmf_fil_bsscfg_data_set(ifp, "bip",
++ &data[offset],
++ WPA_IE_MIN_OUI_LEN);
++ if (err < 0) {
++ brcmf_err("bip error %d\n", err);
++ goto exit;
++ }
++ }
+ }
+ /* FOR WPS , set SES_OW_ENABLED */
+ wsec = (pval | gval | SES_OW_ENABLED);
+@@ -3929,6 +4045,16 @@ brcmf_configure_wpaie(struct brcmf_if *i
+ brcmf_err("wsec error %d\n", err);
+ goto exit;
+ }
++ /* Configure MFP, this needs to go after wsec otherwise the wsec command
++ * will overwrite the values set by MFP
++ */
++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) {
++ err = brcmf_fil_bsscfg_int_set(ifp, "mfp", mfp);
++ if (err < 0) {
++ brcmf_err("mfp error %d\n", err);
++ goto exit;
++ }
++ }
+ /* set upper-layer auth */
+ err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);
+ if (err < 0) {
+@@ -6149,8 +6275,10 @@ static int brcmf_setup_wiphy(struct wiph
+ wiphy->n_addresses = i;
+
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+- wiphy->cipher_suites = __wl_cipher_suites;
+- wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
++ wiphy->cipher_suites = brcmf_cipher_suites;
++ wiphy->n_cipher_suites = ARRAY_SIZE(brcmf_cipher_suites);
++ if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
++ wiphy->n_cipher_suites--;
+ wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
+ WIPHY_FLAG_OFFCHAN_TX |
+ WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -72,7 +72,7 @@
+
+ #define BRCMF_VNDR_IE_P2PAF_SHIFT 12
+
+-#define BRCMF_MAX_DEFAULT_KEYS 4
++#define BRCMF_MAX_DEFAULT_KEYS 6
+
+ /* beacon loss timeout defaults */
+ #define BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON 2
+@@ -107,7 +107,6 @@ struct brcmf_cfg80211_security {
+ u32 auth_type;
+ u32 cipher_pairwise;
+ u32 cipher_group;
+- u32 wpa_auth;
+ };
+
+ /**
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+@@ -161,6 +161,7 @@ void brcmf_feat_attach(struct brcmf_pub
+ ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS);
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable");
++ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MFP, "mfp");
+
+ pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
+ err = brcmf_fil_iovar_data_get(ifp, "pfn_macaddr", &pfn_mac,
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+@@ -30,6 +30,7 @@
+ * WOWL_ND: WOWL net detect (PNO)
+ * WOWL_GTK: (WOWL) GTK rekeying offload
+ * WOWL_ARP_ND: ARP and Neighbor Discovery offload support during WOWL.
++ * MFP: 802.11w Management Frame Protection.
+ */
+ #define BRCMF_FEAT_LIST \
+ BRCMF_FEAT_DEF(MBSS) \
+@@ -42,7 +43,8 @@
+ BRCMF_FEAT_DEF(SCAN_RANDOM_MAC) \
+ BRCMF_FEAT_DEF(WOWL_ND) \
+ BRCMF_FEAT_DEF(WOWL_GTK) \
+- BRCMF_FEAT_DEF(WOWL_ARP_ND)
++ BRCMF_FEAT_DEF(WOWL_ARP_ND) \
++ BRCMF_FEAT_DEF(MFP)
+
+ /*
+ * Quirks:
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+@@ -142,6 +142,10 @@
+ #define BRCMF_RSN_KEK_LENGTH 16
+ #define BRCMF_RSN_REPLAY_LEN 8
+
++#define BRCMF_MFP_NONE 0
++#define BRCMF_MFP_CAPABLE 1
++#define BRCMF_MFP_REQUIRED 2
++
+ /* join preference types for join_pref iovar */
+ enum brcmf_join_pref_types {
+ BRCMF_JOIN_PREF_RSSI = 1,
+--- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
+@@ -236,6 +236,8 @@ static inline bool ac_bitmap_tst(u8 bitm
+ #define WPA2_AUTH_RESERVED3 0x0200
+ #define WPA2_AUTH_RESERVED4 0x0400
+ #define WPA2_AUTH_RESERVED5 0x0800
++#define WPA2_AUTH_1X_SHA256 0x1000 /* 1X with SHA256 key derivation */
++#define WPA2_AUTH_PSK_SHA256 0x8000 /* PSK with SHA256 key derivation */
+
+ #define DOT11_DEFAULT_RTS_LEN 2347
+ #define DOT11_DEFAULT_FRAG_LEN 2346
diff --git a/package/kernel/mac80211/patches/345-brcmfmac-Remove-waitqueue_active-check.patch b/package/kernel/mac80211/patches/345-brcmfmac-Remove-waitqueue_active-check.patch
new file mode 100644
index 0000000000..39f438321e
--- /dev/null
+++ b/package/kernel/mac80211/patches/345-brcmfmac-Remove-waitqueue_active-check.patch
@@ -0,0 +1,54 @@
+From: Hui Wang <hui.wang@canonical.com>
+Date: Wed, 9 Mar 2016 15:25:26 +0800
+Subject: [PATCH] brcmfmac: Remove waitqueue_active check
+
+We met a problem of pm_suspend when repeated closing/opening the lid
+on a Lenovo laptop (1/20 reproduce rate), below is the log:
+
+[ 199.735876] PM: Entering mem sleep
+[ 199.750516] e1000e: EEE TX LPI TIMER: 00000011
+[ 199.856638] Trying to free nonexistent resource <000000000000d000-000000000000d0ff>
+[ 201.753566] brcmfmac: brcmf_pcie_suspend: Timeout on response for entering D3 substate
+[ 201.753581] pci_legacy_suspend(): brcmf_pcie_suspend+0x0/0x1f0 [brcmfmac] returns -5
+[ 201.753585] dpm_run_callback(): pci_pm_suspend+0x0/0x160 returns -5
+[ 201.753589] PM: Device 0000:04:00.0 failed to suspend async: error -5
+
+Through debugging, we found when problem happens, it is not the device
+fails to enter D3, but the signal D3_ACK comes too early to pass the
+waitqueue_active() check.
+
+Just like this:
+brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D3_INFORM);
+// signal is triggered here
+wait_event_timeout(devinfo->mbdata_resp_wait, devinfo->mbdata_completed,
+ BRCMF_PCIE_MBDATA_TIMEOUT);
+
+So far I think it is safe to remove waitqueue_active check since there
+is only one place to trigger this signal (sending
+BRCMF_H2D_HOST_D3_INFORM). And it is not a problem calling wake_up
+event earlier than calling wait_event.
+
+Cc: Brett Rudley <brudley@broadcom.com>
+Cc: Hante Meuleman <meuleman@broadcom.com>
+Cc: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+Cc: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+Cc: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Hui Wang <hui.wang@canonical.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -677,10 +677,8 @@ static void brcmf_pcie_handle_mb_data(st
+ brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
+ if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) {
+ brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
+- if (waitqueue_active(&devinfo->mbdata_resp_wait)) {
+- devinfo->mbdata_completed = true;
+- wake_up(&devinfo->mbdata_resp_wait);
+- }
++ devinfo->mbdata_completed = true;
++ wake_up(&devinfo->mbdata_resp_wait);
+ }
+ }
+
diff --git a/package/kernel/mac80211/patches/346-brcmfmac-uninitialized-ret-variable.patch b/package/kernel/mac80211/patches/346-brcmfmac-uninitialized-ret-variable.patch
new file mode 100644
index 0000000000..3c9ed425da
--- /dev/null
+++ b/package/kernel/mac80211/patches/346-brcmfmac-uninitialized-ret-variable.patch
@@ -0,0 +1,21 @@
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 15 Mar 2016 10:06:10 +0300
+Subject: [PATCH] brcmfmac: uninitialized "ret" variable
+
+There is an error path where "ret" isn't initialized.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -250,7 +250,7 @@ static int brcmf_sdiod_request_data(stru
+ u32 addr, u8 regsz, void *data, bool write)
+ {
+ struct sdio_func *func;
+- int ret;
++ int ret = -EINVAL;
+
+ brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
+ write, fn, addr, regsz);
diff --git a/package/kernel/mac80211/patches/347-brcmfmac-sdio-remove-unused-variable-retry_limit.patch b/package/kernel/mac80211/patches/347-brcmfmac-sdio-remove-unused-variable-retry_limit.patch
new file mode 100644
index 0000000000..d1deb6ee5c
--- /dev/null
+++ b/package/kernel/mac80211/patches/347-brcmfmac-sdio-remove-unused-variable-retry_limit.patch
@@ -0,0 +1,24 @@
+From: Colin Ian King <colin.king@canonical.com>
+Date: Sun, 20 Mar 2016 17:34:52 +0000
+Subject: [PATCH] brcmfmac: sdio: remove unused variable retry_limit
+
+retry_limit has never been used during the life of this driver, so
+we may as well remove it as it is redundant.
+
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Reviewed-by: Julian Calaby <julian.calaby@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -535,9 +535,6 @@ static int qcount[NUMPRIO];
+
+ #define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
+
+-/* Retry count for register access failures */
+-static const uint retry_limit = 2;
+-
+ /* Limit on rounding up frames */
+ static const uint max_roundup = 512;
+
diff --git a/package/kernel/mac80211/patches/348-brcmfmac-Delete-unnecessary-variable-initialisation.patch b/package/kernel/mac80211/patches/348-brcmfmac-Delete-unnecessary-variable-initialisation.patch
new file mode 100644
index 0000000000..d399b264ea
--- /dev/null
+++ b/package/kernel/mac80211/patches/348-brcmfmac-Delete-unnecessary-variable-initialisation.patch
@@ -0,0 +1,26 @@
+From: Markus Elfring <elfring@users.sourceforge.net>
+Date: Fri, 18 Mar 2016 13:23:24 +1100
+Subject: [PATCH] brcmfmac: Delete unnecessary variable initialisation
+
+In brcmf_sdio_download_firmware(), bcmerror is set by the call to
+brcmf_sdio_download_code_file(), before it's checked in the following
+line.
+
+Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
+Acked-by: Arend van Spriel <arend@broadcom.com>
+[Rewrote commit message]
+Signed-off-by: Julian Calaby <julian.calaby@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -3258,7 +3258,7 @@ static int brcmf_sdio_download_firmware(
+ const struct firmware *fw,
+ void *nvram, u32 nvlen)
+ {
+- int bcmerror = -EFAULT;
++ int bcmerror;
+ u32 rstvec;
+
+ sdio_claim_host(bus->sdiodev->func[1]);
diff --git a/package/kernel/mac80211/patches/349-0001-brcmfmac-clear-eventmask-array-before-using-it.patch b/package/kernel/mac80211/patches/349-0001-brcmfmac-clear-eventmask-array-before-using-it.patch
new file mode 100644
index 0000000000..0acb4faaf1
--- /dev/null
+++ b/package/kernel/mac80211/patches/349-0001-brcmfmac-clear-eventmask-array-before-using-it.patch
@@ -0,0 +1,27 @@
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Mon, 11 Apr 2016 11:35:21 +0200
+Subject: [PATCH] brcmfmac: clear eventmask array before using it
+
+When the event_msgs iovar is set an array is used to configure the
+enabled events. This arrays needs to nulled before configuring
+otherwise unhandled events will be enabled. This solves a problem
+where in case of wowl the host got woken by an incorrectly enabled
+event.
+
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+@@ -371,6 +371,7 @@ int brcmf_fweh_activate_events(struct br
+ int i, err;
+ s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+
++ memset(eventmask, 0, sizeof(eventmask));
+ for (i = 0; i < BRCMF_E_LAST; i++) {
+ if (ifp->drvr->fweh.evt_handler[i]) {
+ brcmf_dbg(EVENT, "enable event %s\n",
diff --git a/package/kernel/mac80211/patches/349-0002-brcmfmac-fix-clearing-wowl-wake-indicators.patch b/package/kernel/mac80211/patches/349-0002-brcmfmac-fix-clearing-wowl-wake-indicators.patch
new file mode 100644
index 0000000000..8d3067890c
--- /dev/null
+++ b/package/kernel/mac80211/patches/349-0002-brcmfmac-fix-clearing-wowl-wake-indicators.patch
@@ -0,0 +1,27 @@
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Mon, 11 Apr 2016 11:35:22 +0200
+Subject: [PATCH] brcmfmac: fix clearing wowl wake indicators
+
+Newer firmwares require the usage of the wowl wakeind struct as size
+for the iovar to clear the wake indicators. Older firmwares do not
+care, so change the used size.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -3608,7 +3608,8 @@ static void brcmf_configure_wowl(struct
+ if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
+ wowl_config |= BRCMF_WOWL_UNASSOC;
+
+- brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", strlen("clear"));
++ brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear",
++ sizeof(struct brcmf_wowl_wakeind_le));
+ brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
+ brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
+ brcmf_bus_wowl_config(cfg->pub->bus_if, true);
diff --git a/package/kernel/mac80211/patches/345-brcmfmac-insert-default-boardrev-in-nvram-data-if-mi.patch b/package/kernel/mac80211/patches/349-0003-brcmfmac-insert-default-boardrev-in-nvram-data-if-mi.patch
index f293401ca8..f293401ca8 100644
--- a/package/kernel/mac80211/patches/345-brcmfmac-insert-default-boardrev-in-nvram-data-if-mi.patch
+++ b/package/kernel/mac80211/patches/349-0003-brcmfmac-insert-default-boardrev-in-nvram-data-if-mi.patch
diff --git a/package/kernel/mac80211/patches/349-0004-brcmfmac-fix-p2p-scan-abort-null-pointer-exception.patch b/package/kernel/mac80211/patches/349-0004-brcmfmac-fix-p2p-scan-abort-null-pointer-exception.patch
new file mode 100644
index 0000000000..ed0c83f9bb
--- /dev/null
+++ b/package/kernel/mac80211/patches/349-0004-brcmfmac-fix-p2p-scan-abort-null-pointer-exception.patch
@@ -0,0 +1,29 @@
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Mon, 11 Apr 2016 11:35:24 +0200
+Subject: [PATCH] brcmfmac: fix p2p scan abort null pointer exception
+
+When p2p connection setup is performed without having ever done an
+escan a null pointer exception can occur. This is because the ifp
+to abort scanning is taken from escan struct while it was never
+initialized. Fix this by using the primary ifp for scan abort. The
+abort should still be performed and all scan related commands are
+performed on primary ifp.
+
+Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+@@ -1266,7 +1266,7 @@ static void
+ brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg)
+ {
+ struct brcmf_p2p_info *p2p = &cfg->p2p;
+- struct brcmf_if *ifp = cfg->escan_info.ifp;
++ struct brcmf_if *ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
+
+ if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) &&
+ (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) ||
diff --git a/package/kernel/mac80211/patches/349-0005-brcmfmac-screening-firmware-event-packet.patch b/package/kernel/mac80211/patches/349-0005-brcmfmac-screening-firmware-event-packet.patch
new file mode 100644
index 0000000000..4d26404f51
--- /dev/null
+++ b/package/kernel/mac80211/patches/349-0005-brcmfmac-screening-firmware-event-packet.patch
@@ -0,0 +1,297 @@
+From: Franky Lin <franky.lin@broadcom.com>
+Date: Mon, 11 Apr 2016 11:35:25 +0200
+Subject: [PATCH] brcmfmac: screening firmware event packet
+
+Firmware uses asynchronized events as a communication method to the
+host. The event packets are marked as ETH_P_LINK_CTL protocol type. For
+SDIO and PCIe bus, this kind of packets are delivered through virtual
+event channel not data channel. This patch adds a screening logic to
+make sure the event handler only processes the events coming from the
+correct channel.
+
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+@@ -216,7 +216,9 @@ bool brcmf_c_prec_enq(struct device *dev
+ int prec);
+
+ /* Receive frame for delivery to OS. Callee disposes of rxp. */
+-void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp);
++void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_evnt);
++/* Receive async event packet from firmware. Callee disposes of rxp. */
++void brcmf_rx_event(struct device *dev, struct sk_buff *rxp);
+
+ /* Indication from bus module regarding presence/insertion of dongle. */
+ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -311,16 +311,17 @@ void brcmf_txflowblock(struct device *de
+ brcmf_fws_bus_blocked(drvr, state);
+ }
+
+-void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
++void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb,
++ bool handle_event)
+ {
+- skb->dev = ifp->ndev;
+- skb->protocol = eth_type_trans(skb, skb->dev);
++ skb->protocol = eth_type_trans(skb, ifp->ndev);
+
+ if (skb->pkt_type == PACKET_MULTICAST)
+ ifp->stats.multicast++;
+
+ /* Process special event packets */
+- brcmf_fweh_process_skb(ifp->drvr, skb);
++ if (handle_event)
++ brcmf_fweh_process_skb(ifp->drvr, skb);
+
+ if (!(ifp->ndev->flags & IFF_UP)) {
+ brcmu_pkt_buf_free_skb(skb);
+@@ -381,7 +382,7 @@ static void brcmf_rxreorder_process_info
+ /* validate flags and flow id */
+ if (flags == 0xFF) {
+ brcmf_err("invalid flags...so ignore this packet\n");
+- brcmf_netif_rx(ifp, pkt);
++ brcmf_netif_rx(ifp, pkt, false);
+ return;
+ }
+
+@@ -393,7 +394,7 @@ static void brcmf_rxreorder_process_info
+ if (rfi == NULL) {
+ brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
+ flow_id);
+- brcmf_netif_rx(ifp, pkt);
++ brcmf_netif_rx(ifp, pkt, false);
+ return;
+ }
+
+@@ -418,7 +419,7 @@ static void brcmf_rxreorder_process_info
+ rfi = kzalloc(buf_size, GFP_ATOMIC);
+ if (rfi == NULL) {
+ brcmf_err("failed to alloc buffer\n");
+- brcmf_netif_rx(ifp, pkt);
++ brcmf_netif_rx(ifp, pkt, false);
+ return;
+ }
+
+@@ -532,11 +533,11 @@ static void brcmf_rxreorder_process_info
+ netif_rx:
+ skb_queue_walk_safe(&reorder_list, pkt, pnext) {
+ __skb_unlink(pkt, &reorder_list);
+- brcmf_netif_rx(ifp, pkt);
++ brcmf_netif_rx(ifp, pkt, false);
+ }
+ }
+
+-void brcmf_rx_frame(struct device *dev, struct sk_buff *skb)
++void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt)
+ {
+ struct brcmf_if *ifp;
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+@@ -560,7 +561,32 @@ void brcmf_rx_frame(struct device *dev,
+ if (rd->reorder)
+ brcmf_rxreorder_process_info(ifp, rd->reorder, skb);
+ else
+- brcmf_netif_rx(ifp, skb);
++ brcmf_netif_rx(ifp, skb, handle_evnt);
++}
++
++void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
++{
++ struct brcmf_if *ifp;
++ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++ struct brcmf_pub *drvr = bus_if->drvr;
++ int ret;
++
++ brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
++
++ /* process and remove protocol-specific header */
++ ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
++
++ if (ret || !ifp || !ifp->ndev) {
++ if (ret != -ENODATA && ifp)
++ ifp->stats.rx_errors++;
++ brcmu_pkt_buf_free_skb(skb);
++ return;
++ }
++
++ skb->protocol = eth_type_trans(skb, ifp->ndev);
++
++ brcmf_fweh_process_skb(ifp->drvr, skb);
++ brcmu_pkt_buf_free_skb(skb);
+ }
+
+ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -225,7 +225,8 @@ int brcmf_get_next_free_bsscfgidx(struct
+ void brcmf_txflowblock_if(struct brcmf_if *ifp,
+ enum brcmf_netif_stop_reason reason, bool state);
+ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
+-void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
++void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb,
++ bool handle_event);
+ void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
+ int __init brcmf_core_init(void);
+ void __exit brcmf_core_exit(void);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+@@ -20,6 +20,7 @@
+
+ #include <linux/types.h>
+ #include <linux/netdevice.h>
++#include <linux/etherdevice.h>
+
+ #include <brcmu_utils.h>
+ #include <brcmu_wifi.h>
+@@ -1075,28 +1076,13 @@ static void brcmf_msgbuf_rxbuf_event_pos
+ }
+
+
+-static void
+-brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb,
+- u8 ifidx)
+-{
+- struct brcmf_if *ifp;
+-
+- ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
+- if (!ifp || !ifp->ndev) {
+- brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
+- brcmu_pkt_buf_free_skb(skb);
+- return;
+- }
+- brcmf_netif_rx(ifp, skb);
+-}
+-
+-
+ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
+ {
+ struct msgbuf_rx_event *event;
+ u32 idx;
+ u16 buflen;
+ struct sk_buff *skb;
++ struct brcmf_if *ifp;
+
+ event = (struct msgbuf_rx_event *)buf;
+ idx = le32_to_cpu(event->msg.request_id);
+@@ -1116,7 +1102,19 @@ static void brcmf_msgbuf_process_event(s
+
+ skb_trim(skb, buflen);
+
+- brcmf_msgbuf_rx_skb(msgbuf, skb, event->msg.ifidx);
++ ifp = brcmf_get_ifp(msgbuf->drvr, event->msg.ifidx);
++ if (!ifp || !ifp->ndev) {
++ brcmf_err("Received pkt for invalid ifidx %d\n",
++ event->msg.ifidx);
++ goto exit;
++ }
++
++ skb->protocol = eth_type_trans(skb, ifp->ndev);
++
++ brcmf_fweh_process_skb(ifp->drvr, skb);
++
++exit:
++ brcmu_pkt_buf_free_skb(skb);
+ }
+
+
+@@ -1128,6 +1126,7 @@ brcmf_msgbuf_process_rx_complete(struct
+ u16 data_offset;
+ u16 buflen;
+ u32 idx;
++ struct brcmf_if *ifp;
+
+ brcmf_msgbuf_update_rxbufpost_count(msgbuf, 1);
+
+@@ -1148,7 +1147,14 @@ brcmf_msgbuf_process_rx_complete(struct
+
+ skb_trim(skb, buflen);
+
+- brcmf_msgbuf_rx_skb(msgbuf, skb, rx_complete->msg.ifidx);
++ ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
++ if (!ifp || !ifp->ndev) {
++ brcmf_err("Received pkt for invalid ifidx %d\n",
++ rx_complete->msg.ifidx);
++ brcmu_pkt_buf_free_skb(skb);
++ return;
++ }
++ brcmf_netif_rx(ifp, skb, false);
+ }
+
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -1294,6 +1294,17 @@ static inline u8 brcmf_sdio_getdatoffset
+ return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT);
+ }
+
++static inline bool brcmf_sdio_fromevntchan(u8 *swheader)
++{
++ u32 hdrvalue;
++ u8 ret;
++
++ hdrvalue = *(u32 *)swheader;
++ ret = (u8)((hdrvalue & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT);
++
++ return (ret == SDPCM_EVENT_CHANNEL);
++}
++
+ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
+ struct brcmf_sdio_hdrinfo *rd,
+ enum brcmf_sdio_frmtype type)
+@@ -1641,7 +1652,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf
+ pfirst->len, pfirst->next,
+ pfirst->prev);
+ skb_unlink(pfirst, &bus->glom);
+- brcmf_rx_frame(bus->sdiodev->dev, pfirst);
++ if (brcmf_sdio_fromevntchan(pfirst->data))
++ brcmf_rx_event(bus->sdiodev->dev, pfirst);
++ else
++ brcmf_rx_frame(bus->sdiodev->dev, pfirst,
++ false);
+ bus->sdcnt.rxglompkts++;
+ }
+
+@@ -1967,18 +1982,19 @@ static uint brcmf_sdio_readframes(struct
+ __skb_trim(pkt, rd->len);
+ skb_pull(pkt, rd->dat_offset);
+
++ if (pkt->len == 0)
++ brcmu_pkt_buf_free_skb(pkt);
++ else if (rd->channel == SDPCM_EVENT_CHANNEL)
++ brcmf_rx_event(bus->sdiodev->dev, pkt);
++ else
++ brcmf_rx_frame(bus->sdiodev->dev, pkt,
++ false);
++
+ /* prepare the descriptor for the next read */
+ rd->len = rd->len_nxtfrm << 4;
+ rd->len_nxtfrm = 0;
+ /* treat all packet as event if we don't know */
+ rd->channel = SDPCM_EVENT_CHANNEL;
+-
+- if (pkt->len == 0) {
+- brcmu_pkt_buf_free_skb(pkt);
+- continue;
+- }
+-
+- brcmf_rx_frame(bus->sdiodev->dev, pkt);
+ }
+
+ rxcount = maxframes - rxleft;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+@@ -514,7 +514,7 @@ static void brcmf_usb_rx_complete(struct
+
+ if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
+ skb_put(skb, urb->actual_length);
+- brcmf_rx_frame(devinfo->dev, skb);
++ brcmf_rx_frame(devinfo->dev, skb, true);
+ brcmf_usb_rx_refill(devinfo, req);
+ } else {
+ brcmu_pkt_buf_free_skb(skb);
diff --git a/package/kernel/mac80211/patches/349-0006-brcmfmac-cleanup-ampdu-rx-host-reorder-code.patch b/package/kernel/mac80211/patches/349-0006-brcmfmac-cleanup-ampdu-rx-host-reorder-code.patch
new file mode 100644
index 0000000000..33b263df3a
--- /dev/null
+++ b/package/kernel/mac80211/patches/349-0006-brcmfmac-cleanup-ampdu-rx-host-reorder-code.patch
@@ -0,0 +1,585 @@
+From: Arend van Spriel <arend@broadcom.com>
+Date: Mon, 11 Apr 2016 11:35:26 +0200
+Subject: [PATCH] brcmfmac: cleanup ampdu-rx host reorder code
+
+The code for ampdu-rx host reorder is related to the firmware signalling
+supported in BCDC protocol. This change moves the code to fwsignal module.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
+@@ -351,6 +351,12 @@ brcmf_proto_bcdc_add_tdls_peer(struct br
+ {
+ }
+
++static void brcmf_proto_bcdc_rxreorder(struct brcmf_if *ifp,
++ struct sk_buff *skb)
++{
++ brcmf_fws_rxreorder(ifp, skb);
++}
++
+ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
+ {
+ struct brcmf_bcdc *bcdc;
+@@ -372,6 +378,7 @@ int brcmf_proto_bcdc_attach(struct brcmf
+ drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
+ drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
+ drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer;
++ drvr->proto->rxreorder = brcmf_proto_bcdc_rxreorder;
+ drvr->proto->pd = bcdc;
+
+ drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -40,19 +40,6 @@
+
+ #define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950)
+
+-/* AMPDU rx reordering definitions */
+-#define BRCMF_RXREORDER_FLOWID_OFFSET 0
+-#define BRCMF_RXREORDER_MAXIDX_OFFSET 2
+-#define BRCMF_RXREORDER_FLAGS_OFFSET 4
+-#define BRCMF_RXREORDER_CURIDX_OFFSET 6
+-#define BRCMF_RXREORDER_EXPIDX_OFFSET 8
+-
+-#define BRCMF_RXREORDER_DEL_FLOW 0x01
+-#define BRCMF_RXREORDER_FLUSH_ALL 0x02
+-#define BRCMF_RXREORDER_CURIDX_VALID 0x04
+-#define BRCMF_RXREORDER_EXPIDX_VALID 0x08
+-#define BRCMF_RXREORDER_NEW_HOLE 0x10
+-
+ #define BRCMF_BSSIDX_INVALID -1
+
+ char *brcmf_ifname(struct brcmf_if *ifp)
+@@ -342,207 +329,11 @@ void brcmf_netif_rx(struct brcmf_if *ifp
+ netif_rx_ni(skb);
+ }
+
+-static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
+- u8 start, u8 end,
+- struct sk_buff_head *skb_list)
+-{
+- /* initialize return list */
+- __skb_queue_head_init(skb_list);
+-
+- if (rfi->pend_pkts == 0) {
+- brcmf_dbg(INFO, "no packets in reorder queue\n");
+- return;
+- }
+-
+- do {
+- if (rfi->pktslots[start]) {
+- __skb_queue_tail(skb_list, rfi->pktslots[start]);
+- rfi->pktslots[start] = NULL;
+- }
+- start++;
+- if (start > rfi->max_idx)
+- start = 0;
+- } while (start != end);
+- rfi->pend_pkts -= skb_queue_len(skb_list);
+-}
+-
+-static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data,
+- struct sk_buff *pkt)
+-{
+- u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
+- struct brcmf_ampdu_rx_reorder *rfi;
+- struct sk_buff_head reorder_list;
+- struct sk_buff *pnext;
+- u8 flags;
+- u32 buf_size;
+-
+- flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
+- flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
+-
+- /* validate flags and flow id */
+- if (flags == 0xFF) {
+- brcmf_err("invalid flags...so ignore this packet\n");
+- brcmf_netif_rx(ifp, pkt, false);
+- return;
+- }
+-
+- rfi = ifp->drvr->reorder_flows[flow_id];
+- if (flags & BRCMF_RXREORDER_DEL_FLOW) {
+- brcmf_dbg(INFO, "flow-%d: delete\n",
+- flow_id);
+-
+- if (rfi == NULL) {
+- brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
+- flow_id);
+- brcmf_netif_rx(ifp, pkt, false);
+- return;
+- }
+-
+- brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
+- &reorder_list);
+- /* add the last packet */
+- __skb_queue_tail(&reorder_list, pkt);
+- kfree(rfi);
+- ifp->drvr->reorder_flows[flow_id] = NULL;
+- goto netif_rx;
+- }
+- /* from here on we need a flow reorder instance */
+- if (rfi == NULL) {
+- buf_size = sizeof(*rfi);
+- max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
+-
+- buf_size += (max_idx + 1) * sizeof(pkt);
+-
+- /* allocate space for flow reorder info */
+- brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
+- flow_id, max_idx);
+- rfi = kzalloc(buf_size, GFP_ATOMIC);
+- if (rfi == NULL) {
+- brcmf_err("failed to alloc buffer\n");
+- brcmf_netif_rx(ifp, pkt, false);
+- return;
+- }
+-
+- ifp->drvr->reorder_flows[flow_id] = rfi;
+- rfi->pktslots = (struct sk_buff **)(rfi+1);
+- rfi->max_idx = max_idx;
+- }
+- if (flags & BRCMF_RXREORDER_NEW_HOLE) {
+- if (rfi->pend_pkts) {
+- brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
+- rfi->exp_idx,
+- &reorder_list);
+- WARN_ON(rfi->pend_pkts);
+- } else {
+- __skb_queue_head_init(&reorder_list);
+- }
+- rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
+- rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
+- rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
+- rfi->pktslots[rfi->cur_idx] = pkt;
+- rfi->pend_pkts++;
+- brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
+- flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
+- } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
+- cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
+- exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
+-
+- if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
+- /* still in the current hole */
+- /* enqueue the current on the buffer chain */
+- if (rfi->pktslots[cur_idx] != NULL) {
+- brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
+- brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
+- rfi->pktslots[cur_idx] = NULL;
+- }
+- rfi->pktslots[cur_idx] = pkt;
+- rfi->pend_pkts++;
+- rfi->cur_idx = cur_idx;
+- brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
+- flow_id, cur_idx, exp_idx, rfi->pend_pkts);
+-
+- /* can return now as there is no reorder
+- * list to process.
+- */
+- return;
+- }
+- if (rfi->exp_idx == cur_idx) {
+- if (rfi->pktslots[cur_idx] != NULL) {
+- brcmf_dbg(INFO, "error buffer pending..free it\n");
+- brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
+- rfi->pktslots[cur_idx] = NULL;
+- }
+- rfi->pktslots[cur_idx] = pkt;
+- rfi->pend_pkts++;
+-
+- /* got the expected one. flush from current to expected
+- * and update expected
+- */
+- brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
+- flow_id, cur_idx, exp_idx, rfi->pend_pkts);
+-
+- rfi->cur_idx = cur_idx;
+- rfi->exp_idx = exp_idx;
+-
+- brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
+- &reorder_list);
+- brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
+- flow_id, skb_queue_len(&reorder_list),
+- rfi->pend_pkts);
+- } else {
+- u8 end_idx;
+-
+- brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
+- flow_id, flags, rfi->cur_idx, rfi->exp_idx,
+- cur_idx, exp_idx);
+- if (flags & BRCMF_RXREORDER_FLUSH_ALL)
+- end_idx = rfi->exp_idx;
+- else
+- end_idx = exp_idx;
+-
+- /* flush pkts first */
+- brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
+- &reorder_list);
+-
+- if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
+- __skb_queue_tail(&reorder_list, pkt);
+- } else {
+- rfi->pktslots[cur_idx] = pkt;
+- rfi->pend_pkts++;
+- }
+- rfi->exp_idx = exp_idx;
+- rfi->cur_idx = cur_idx;
+- }
+- } else {
+- /* explicity window move updating the expected index */
+- exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
+-
+- brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
+- flow_id, flags, rfi->exp_idx, exp_idx);
+- if (flags & BRCMF_RXREORDER_FLUSH_ALL)
+- end_idx = rfi->exp_idx;
+- else
+- end_idx = exp_idx;
+-
+- brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
+- &reorder_list);
+- __skb_queue_tail(&reorder_list, pkt);
+- /* set the new expected idx */
+- rfi->exp_idx = exp_idx;
+- }
+-netif_rx:
+- skb_queue_walk_safe(&reorder_list, pkt, pnext) {
+- __skb_unlink(pkt, &reorder_list);
+- brcmf_netif_rx(ifp, pkt, false);
+- }
+-}
+-
+ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt)
+ {
+ struct brcmf_if *ifp;
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_pub *drvr = bus_if->drvr;
+- struct brcmf_skb_reorder_data *rd;
+ int ret;
+
+ brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
+@@ -557,9 +348,8 @@ void brcmf_rx_frame(struct device *dev,
+ return;
+ }
+
+- rd = (struct brcmf_skb_reorder_data *)skb->cb;
+- if (rd->reorder)
+- brcmf_rxreorder_process_info(ifp, rd->reorder, skb);
++ if (brcmf_proto_is_reorder_skb(skb))
++ brcmf_proto_rxreorder(ifp, skb);
+ else
+ brcmf_netif_rx(ifp, skb, handle_evnt);
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -208,10 +208,6 @@ struct brcmf_if {
+ u8 ipv6addr_idx;
+ };
+
+-struct brcmf_skb_reorder_data {
+- u8 *reorder;
+-};
+-
+ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
+
+ /* Return pointer to interface name */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+@@ -92,6 +92,19 @@ enum brcmf_fws_tlv_len {
+ };
+ #undef BRCMF_FWS_TLV_DEF
+
++/* AMPDU rx reordering definitions */
++#define BRCMF_RXREORDER_FLOWID_OFFSET 0
++#define BRCMF_RXREORDER_MAXIDX_OFFSET 2
++#define BRCMF_RXREORDER_FLAGS_OFFSET 4
++#define BRCMF_RXREORDER_CURIDX_OFFSET 6
++#define BRCMF_RXREORDER_EXPIDX_OFFSET 8
++
++#define BRCMF_RXREORDER_DEL_FLOW 0x01
++#define BRCMF_RXREORDER_FLUSH_ALL 0x02
++#define BRCMF_RXREORDER_CURIDX_VALID 0x04
++#define BRCMF_RXREORDER_EXPIDX_VALID 0x08
++#define BRCMF_RXREORDER_NEW_HOLE 0x10
++
+ #ifdef DEBUG
+ /*
+ * brcmf_fws_tlv_names - array of tlv names.
+@@ -1614,6 +1627,202 @@ static int brcmf_fws_notify_bcmc_credit_
+ return 0;
+ }
+
++static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
++ u8 start, u8 end,
++ struct sk_buff_head *skb_list)
++{
++ /* initialize return list */
++ __skb_queue_head_init(skb_list);
++
++ if (rfi->pend_pkts == 0) {
++ brcmf_dbg(INFO, "no packets in reorder queue\n");
++ return;
++ }
++
++ do {
++ if (rfi->pktslots[start]) {
++ __skb_queue_tail(skb_list, rfi->pktslots[start]);
++ rfi->pktslots[start] = NULL;
++ }
++ start++;
++ if (start > rfi->max_idx)
++ start = 0;
++ } while (start != end);
++ rfi->pend_pkts -= skb_queue_len(skb_list);
++}
++
++void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt)
++{
++ u8 *reorder_data;
++ u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
++ struct brcmf_ampdu_rx_reorder *rfi;
++ struct sk_buff_head reorder_list;
++ struct sk_buff *pnext;
++ u8 flags;
++ u32 buf_size;
++
++ reorder_data = ((struct brcmf_skb_reorder_data *)pkt->cb)->reorder;
++ flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
++ flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
++
++ /* validate flags and flow id */
++ if (flags == 0xFF) {
++ brcmf_err("invalid flags...so ignore this packet\n");
++ brcmf_netif_rx(ifp, pkt, false);
++ return;
++ }
++
++ rfi = ifp->drvr->reorder_flows[flow_id];
++ if (flags & BRCMF_RXREORDER_DEL_FLOW) {
++ brcmf_dbg(INFO, "flow-%d: delete\n",
++ flow_id);
++
++ if (rfi == NULL) {
++ brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
++ flow_id);
++ brcmf_netif_rx(ifp, pkt, false);
++ return;
++ }
++
++ brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
++ &reorder_list);
++ /* add the last packet */
++ __skb_queue_tail(&reorder_list, pkt);
++ kfree(rfi);
++ ifp->drvr->reorder_flows[flow_id] = NULL;
++ goto netif_rx;
++ }
++ /* from here on we need a flow reorder instance */
++ if (rfi == NULL) {
++ buf_size = sizeof(*rfi);
++ max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
++
++ buf_size += (max_idx + 1) * sizeof(pkt);
++
++ /* allocate space for flow reorder info */
++ brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
++ flow_id, max_idx);
++ rfi = kzalloc(buf_size, GFP_ATOMIC);
++ if (rfi == NULL) {
++ brcmf_err("failed to alloc buffer\n");
++ brcmf_netif_rx(ifp, pkt, false);
++ return;
++ }
++
++ ifp->drvr->reorder_flows[flow_id] = rfi;
++ rfi->pktslots = (struct sk_buff **)(rfi + 1);
++ rfi->max_idx = max_idx;
++ }
++ if (flags & BRCMF_RXREORDER_NEW_HOLE) {
++ if (rfi->pend_pkts) {
++ brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
++ rfi->exp_idx,
++ &reorder_list);
++ WARN_ON(rfi->pend_pkts);
++ } else {
++ __skb_queue_head_init(&reorder_list);
++ }
++ rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
++ rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
++ rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
++ rfi->pktslots[rfi->cur_idx] = pkt;
++ rfi->pend_pkts++;
++ brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
++ flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
++ } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
++ cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
++ exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
++
++ if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
++ /* still in the current hole */
++ /* enqueue the current on the buffer chain */
++ if (rfi->pktslots[cur_idx] != NULL) {
++ brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
++ brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
++ rfi->pktslots[cur_idx] = NULL;
++ }
++ rfi->pktslots[cur_idx] = pkt;
++ rfi->pend_pkts++;
++ rfi->cur_idx = cur_idx;
++ brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
++ flow_id, cur_idx, exp_idx, rfi->pend_pkts);
++
++ /* can return now as there is no reorder
++ * list to process.
++ */
++ return;
++ }
++ if (rfi->exp_idx == cur_idx) {
++ if (rfi->pktslots[cur_idx] != NULL) {
++ brcmf_dbg(INFO, "error buffer pending..free it\n");
++ brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
++ rfi->pktslots[cur_idx] = NULL;
++ }
++ rfi->pktslots[cur_idx] = pkt;
++ rfi->pend_pkts++;
++
++ /* got the expected one. flush from current to expected
++ * and update expected
++ */
++ brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
++ flow_id, cur_idx, exp_idx, rfi->pend_pkts);
++
++ rfi->cur_idx = cur_idx;
++ rfi->exp_idx = exp_idx;
++
++ brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
++ &reorder_list);
++ brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
++ flow_id, skb_queue_len(&reorder_list),
++ rfi->pend_pkts);
++ } else {
++ u8 end_idx;
++
++ brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
++ flow_id, flags, rfi->cur_idx, rfi->exp_idx,
++ cur_idx, exp_idx);
++ if (flags & BRCMF_RXREORDER_FLUSH_ALL)
++ end_idx = rfi->exp_idx;
++ else
++ end_idx = exp_idx;
++
++ /* flush pkts first */
++ brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
++ &reorder_list);
++
++ if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
++ __skb_queue_tail(&reorder_list, pkt);
++ } else {
++ rfi->pktslots[cur_idx] = pkt;
++ rfi->pend_pkts++;
++ }
++ rfi->exp_idx = exp_idx;
++ rfi->cur_idx = cur_idx;
++ }
++ } else {
++ /* explicity window move updating the expected index */
++ exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
++
++ brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
++ flow_id, flags, rfi->exp_idx, exp_idx);
++ if (flags & BRCMF_RXREORDER_FLUSH_ALL)
++ end_idx = rfi->exp_idx;
++ else
++ end_idx = exp_idx;
++
++ brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
++ &reorder_list);
++ __skb_queue_tail(&reorder_list, pkt);
++ /* set the new expected idx */
++ rfi->exp_idx = exp_idx;
++ }
++netif_rx:
++ skb_queue_walk_safe(&reorder_list, pkt, pnext) {
++ __skb_unlink(pkt, &reorder_list);
++ brcmf_netif_rx(ifp, pkt, false);
++ }
++}
++
+ void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
+ {
+ struct brcmf_skb_reorder_data *rd;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
+@@ -29,5 +29,6 @@ void brcmf_fws_add_interface(struct brcm
+ void brcmf_fws_del_interface(struct brcmf_if *ifp);
+ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
+ void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked);
++void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb);
+
+ #endif /* FWSIGNAL_H_ */
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+@@ -527,6 +527,9 @@ static int brcmf_msgbuf_hdrpull(struct b
+ return -ENODEV;
+ }
+
++static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
++{
++}
+
+ static void
+ brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid)
+@@ -1466,6 +1469,7 @@ int brcmf_proto_msgbuf_attach(struct brc
+ drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
+ drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
+ drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
++ drvr->proto->rxreorder = brcmf_msgbuf_rxreorder;
+ drvr->proto->pd = msgbuf;
+
+ init_waitqueue_head(&msgbuf->ioctl_resp_wait);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
+@@ -22,6 +22,9 @@ enum proto_addr_mode {
+ ADDR_DIRECT
+ };
+
++struct brcmf_skb_reorder_data {
++ u8 *reorder;
++};
+
+ struct brcmf_proto {
+ int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
+@@ -38,6 +41,7 @@ struct brcmf_proto {
+ u8 peer[ETH_ALEN]);
+ void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx,
+ u8 peer[ETH_ALEN]);
++ void (*rxreorder)(struct brcmf_if *ifp, struct sk_buff *skb);
+ void *pd;
+ };
+
+@@ -91,6 +95,18 @@ brcmf_proto_add_tdls_peer(struct brcmf_p
+ {
+ drvr->proto->add_tdls_peer(drvr, ifidx, peer);
+ }
++static inline bool brcmf_proto_is_reorder_skb(struct sk_buff *skb)
++{
++ struct brcmf_skb_reorder_data *rd;
++
++ rd = (struct brcmf_skb_reorder_data *)skb->cb;
++ return !!rd->reorder;
++}
+
++static inline void
++brcmf_proto_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
++{
++ ifp->drvr->proto->rxreorder(ifp, skb);
++}
+
+ #endif /* BRCMFMAC_PROTO_H */
diff --git a/package/kernel/mac80211/patches/349-0007-brcmfmac-revise-handling-events-in-receive-path.patch b/package/kernel/mac80211/patches/349-0007-brcmfmac-revise-handling-events-in-receive-path.patch
new file mode 100644
index 0000000000..a43feffe17
--- /dev/null
+++ b/package/kernel/mac80211/patches/349-0007-brcmfmac-revise-handling-events-in-receive-path.patch
@@ -0,0 +1,139 @@
+From: Arend van Spriel <arend@broadcom.com>
+Date: Mon, 11 Apr 2016 11:35:27 +0200
+Subject: [PATCH] brcmfmac: revise handling events in receive path
+
+Move event handling out of brcmf_netif_rx() avoiding the need
+to pass a flag. This flag is only ever true for USB hosts as
+other interface use separate brcmf_rx_event() function.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+@@ -216,7 +216,7 @@ bool brcmf_c_prec_enq(struct device *dev
+ int prec);
+
+ /* Receive frame for delivery to OS. Callee disposes of rxp. */
+-void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_evnt);
++void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_event);
+ /* Receive async event packet from firmware. Callee disposes of rxp. */
+ void brcmf_rx_event(struct device *dev, struct sk_buff *rxp);
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -298,18 +298,11 @@ void brcmf_txflowblock(struct device *de
+ brcmf_fws_bus_blocked(drvr, state);
+ }
+
+-void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb,
+- bool handle_event)
++void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
+ {
+- skb->protocol = eth_type_trans(skb, ifp->ndev);
+-
+ if (skb->pkt_type == PACKET_MULTICAST)
+ ifp->stats.multicast++;
+
+- /* Process special event packets */
+- if (handle_event)
+- brcmf_fweh_process_skb(ifp->drvr, skb);
+-
+ if (!(ifp->ndev->flags & IFF_UP)) {
+ brcmu_pkt_buf_free_skb(skb);
+ return;
+@@ -329,7 +322,7 @@ void brcmf_netif_rx(struct brcmf_if *ifp
+ netif_rx_ni(skb);
+ }
+
+-void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt)
++void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
+ {
+ struct brcmf_if *ifp;
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+@@ -348,10 +341,17 @@ void brcmf_rx_frame(struct device *dev,
+ return;
+ }
+
+- if (brcmf_proto_is_reorder_skb(skb))
++ skb->protocol = eth_type_trans(skb, ifp->ndev);
++
++ if (brcmf_proto_is_reorder_skb(skb)) {
+ brcmf_proto_rxreorder(ifp, skb);
+- else
+- brcmf_netif_rx(ifp, skb, handle_evnt);
++ } else {
++ /* Process special event packets */
++ if (handle_event)
++ brcmf_fweh_process_skb(ifp->drvr, skb);
++
++ brcmf_netif_rx(ifp, skb);
++ }
+ }
+
+ void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -221,8 +221,7 @@ int brcmf_get_next_free_bsscfgidx(struct
+ void brcmf_txflowblock_if(struct brcmf_if *ifp,
+ enum brcmf_netif_stop_reason reason, bool state);
+ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
+-void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb,
+- bool handle_event);
++void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
+ void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
+ int __init brcmf_core_init(void);
+ void __exit brcmf_core_exit(void);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+@@ -1668,7 +1668,7 @@ void brcmf_fws_rxreorder(struct brcmf_if
+ /* validate flags and flow id */
+ if (flags == 0xFF) {
+ brcmf_err("invalid flags...so ignore this packet\n");
+- brcmf_netif_rx(ifp, pkt, false);
++ brcmf_netif_rx(ifp, pkt);
+ return;
+ }
+
+@@ -1680,7 +1680,7 @@ void brcmf_fws_rxreorder(struct brcmf_if
+ if (rfi == NULL) {
+ brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
+ flow_id);
+- brcmf_netif_rx(ifp, pkt, false);
++ brcmf_netif_rx(ifp, pkt);
+ return;
+ }
+
+@@ -1705,7 +1705,7 @@ void brcmf_fws_rxreorder(struct brcmf_if
+ rfi = kzalloc(buf_size, GFP_ATOMIC);
+ if (rfi == NULL) {
+ brcmf_err("failed to alloc buffer\n");
+- brcmf_netif_rx(ifp, pkt, false);
++ brcmf_netif_rx(ifp, pkt);
+ return;
+ }
+
+@@ -1819,7 +1819,7 @@ void brcmf_fws_rxreorder(struct brcmf_if
+ netif_rx:
+ skb_queue_walk_safe(&reorder_list, pkt, pnext) {
+ __skb_unlink(pkt, &reorder_list);
+- brcmf_netif_rx(ifp, pkt, false);
++ brcmf_netif_rx(ifp, pkt);
+ }
+ }
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+@@ -1157,7 +1157,7 @@ brcmf_msgbuf_process_rx_complete(struct
+ brcmu_pkt_buf_free_skb(skb);
+ return;
+ }
+- brcmf_netif_rx(ifp, skb, false);
++ brcmf_netif_rx(ifp, skb);
+ }
+
+
diff --git a/package/kernel/mac80211/patches/349-0008-brcmfmac-create-common-function-for-handling-brcmf_p.patch b/package/kernel/mac80211/patches/349-0008-brcmfmac-create-common-function-for-handling-brcmf_p.patch
new file mode 100644
index 0000000000..08ea235fdd
--- /dev/null
+++ b/package/kernel/mac80211/patches/349-0008-brcmfmac-create-common-function-for-handling-brcmf_p.patch
@@ -0,0 +1,88 @@
+From: Arend van Spriel <arend@broadcom.com>
+Date: Mon, 11 Apr 2016 11:35:28 +0200
+Subject: [PATCH] brcmfmac: create common function for handling
+ brcmf_proto_hdrpull()
+
+In receive path brcmf_proto_hdrpull() needs to be called and handled
+similar in brcmf_rx_frame() and brcmf_rx_event(). Move that duplicated
+code in separate function.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -322,26 +322,35 @@ void brcmf_netif_rx(struct brcmf_if *ifp
+ netif_rx_ni(skb);
+ }
+
+-void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
++static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
++ struct brcmf_if **ifp)
+ {
+- struct brcmf_if *ifp;
+- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+- struct brcmf_pub *drvr = bus_if->drvr;
+ int ret;
+
+- brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
+-
+ /* process and remove protocol-specific header */
+- ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
++ ret = brcmf_proto_hdrpull(drvr, true, skb, ifp);
+
+- if (ret || !ifp || !ifp->ndev) {
++ if (ret || !(*ifp) || !(*ifp)->ndev) {
+ if (ret != -ENODATA && ifp)
+- ifp->stats.rx_errors++;
++ (*ifp)->stats.rx_errors++;
+ brcmu_pkt_buf_free_skb(skb);
+- return;
++ return -ENODATA;
+ }
+
+- skb->protocol = eth_type_trans(skb, ifp->ndev);
++ skb->protocol = eth_type_trans(skb, (*ifp)->ndev);
++ return 0;
++}
++
++void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
++{
++ struct brcmf_if *ifp;
++ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++ struct brcmf_pub *drvr = bus_if->drvr;
++
++ brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
++
++ if (brcmf_rx_hdrpull(drvr, skb, &ifp))
++ return;
+
+ if (brcmf_proto_is_reorder_skb(skb)) {
+ brcmf_proto_rxreorder(ifp, skb);
+@@ -359,21 +368,11 @@ void brcmf_rx_event(struct device *dev,
+ struct brcmf_if *ifp;
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_pub *drvr = bus_if->drvr;
+- int ret;
+
+ brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
+
+- /* process and remove protocol-specific header */
+- ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
+-
+- if (ret || !ifp || !ifp->ndev) {
+- if (ret != -ENODATA && ifp)
+- ifp->stats.rx_errors++;
+- brcmu_pkt_buf_free_skb(skb);
++ if (brcmf_rx_hdrpull(drvr, skb, &ifp))
+ return;
+- }
+-
+- skb->protocol = eth_type_trans(skb, ifp->ndev);
+
+ brcmf_fweh_process_skb(ifp->drvr, skb);
+ brcmu_pkt_buf_free_skb(skb);
diff --git a/package/kernel/mac80211/patches/351-0005-brcmfmac-rework-function-picking-free-BSS-index.patch b/package/kernel/mac80211/patches/351-0005-brcmfmac-rework-function-picking-free-BSS-index.patch
index 6719f2ba51..c602f2272a 100644
--- a/package/kernel/mac80211/patches/351-0005-brcmfmac-rework-function-picking-free-BSS-index.patch
+++ b/package/kernel/mac80211/patches/351-0005-brcmfmac-rework-function-picking-free-BSS-index.patch
@@ -43,7 +43,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -506,6 +506,21 @@ brcmf_cfg80211_update_proto_addr_mode(st
+@@ -527,6 +527,21 @@ brcmf_cfg80211_update_proto_addr_mode(st
ADDR_INDIRECT);
}
@@ -65,7 +65,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
{
struct brcmf_mbss_ssid_le mbss_ssid_le;
-@@ -513,7 +528,7 @@ static int brcmf_cfg80211_request_ap_if(
+@@ -534,7 +549,7 @@ static int brcmf_cfg80211_request_ap_if(
int err;
memset(&mbss_ssid_le, 0, sizeof(mbss_ssid_le));
@@ -76,7 +76,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -909,30 +909,6 @@ void brcmf_remove_interface(struct brcmf
+@@ -753,30 +753,6 @@ void brcmf_remove_interface(struct brcmf
brcmf_del_if(ifp->drvr, ifp->bsscfgidx);
}
@@ -109,7 +109,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
static int brcmf_inetaddr_changed(struct notifier_block *nb,
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-@@ -214,7 +214,6 @@ int brcmf_net_attach(struct brcmf_if *if
+@@ -217,7 +217,6 @@ int brcmf_net_attach(struct brcmf_if *if
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
bool is_p2pdev, char *name, u8 *mac_addr);
void brcmf_remove_interface(struct brcmf_if *ifp);
diff --git a/package/kernel/mac80211/patches/351-0007-brcmutil-add-field-storing-control-channel-to-the-st.patch b/package/kernel/mac80211/patches/351-0007-brcmutil-add-field-storing-control-channel-to-the-st.patch
index a7074a2ef6..a79c9a2e93 100644
--- a/package/kernel/mac80211/patches/351-0007-brcmutil-add-field-storing-control-channel-to-the-st.patch
+++ b/package/kernel/mac80211/patches/351-0007-brcmutil-add-field-storing-control-channel-to-the-st.patch
@@ -27,7 +27,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2690,7 +2690,7 @@ static s32 brcmf_inform_single_bss(struc
+@@ -2689,7 +2689,7 @@ static s32 brcmf_inform_single_bss(struc
if (!bi->ctl_ch) {
ch.chspec = le16_to_cpu(bi->chanspec);
cfg->d11inf.decchspec(&ch);
@@ -36,7 +36,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
}
channel = bi->ctl_ch;
-@@ -2808,7 +2808,7 @@ static s32 brcmf_inform_ibss(struct brcm
+@@ -2807,7 +2807,7 @@ static s32 brcmf_inform_ibss(struct brcm
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
@@ -45,7 +45,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
cfg->channel = freq;
notify_channel = ieee80211_get_channel(wiphy, freq);
-@@ -2818,7 +2818,7 @@ static s32 brcmf_inform_ibss(struct brcm
+@@ -2817,7 +2817,7 @@ static s32 brcmf_inform_ibss(struct brcm
notify_ielen = le32_to_cpu(bi->ie_length);
notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
@@ -54,7 +54,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
brcmf_dbg(CONN, "capability: %X\n", notify_capability);
brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
brcmf_dbg(CONN, "signal: %d\n", notify_signal);
-@@ -5132,7 +5132,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg8
+@@ -5235,7 +5235,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg8
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
@@ -63,7 +63,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
notify_channel = ieee80211_get_channel(wiphy, freq);
done:
-@@ -5654,14 +5654,15 @@ static int brcmf_construct_chaninfo(stru
+@@ -5757,14 +5757,15 @@ static int brcmf_construct_chaninfo(stru
channel = band->channels;
index = band->n_channels;
for (j = 0; j < band->n_channels; j++) {
@@ -82,7 +82,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
/* assuming the chanspecs order is HT20,
* HT40 upper, HT40 lower, and VHT80.
-@@ -5763,7 +5764,7 @@ static int brcmf_enable_bw40_2g(struct b
+@@ -5866,7 +5867,7 @@ static int brcmf_enable_bw40_2g(struct b
if (WARN_ON(ch.bw != BRCMU_CHAN_BW_40))
continue;
for (j = 0; j < band->n_channels; j++) {
@@ -102,7 +102,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
}
afx_hdl->peer_chan = bi->ctl_ch;
brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n",
-@@ -1380,7 +1380,7 @@ int brcmf_p2p_notify_action_frame_rx(str
+@@ -1385,7 +1385,7 @@ int brcmf_p2p_notify_action_frame_rx(str
if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
&p2p->status) &&
(ether_addr_equal(afx_hdl->tx_dst_addr, e->addr))) {
@@ -111,7 +111,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n",
afx_hdl->peer_chan);
complete(&afx_hdl->act_frm_scan);
-@@ -1423,7 +1423,7 @@ int brcmf_p2p_notify_action_frame_rx(str
+@@ -1428,7 +1428,7 @@ int brcmf_p2p_notify_action_frame_rx(str
memcpy(&mgmt_frame->u, frame, mgmt_frame_len);
mgmt_frame_len += offsetof(struct ieee80211_mgmt, u);
@@ -120,7 +120,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
ch.band == BRCMU_CHAN_BAND_2G ?
IEEE80211_BAND_2GHZ :
IEEE80211_BAND_5GHZ);
-@@ -1863,7 +1863,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probere
+@@ -1873,7 +1873,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probere
if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) &&
(ether_addr_equal(afx_hdl->tx_dst_addr, e->addr))) {
@@ -129,7 +129,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n",
afx_hdl->peer_chan);
complete(&afx_hdl->act_frm_scan);
-@@ -1888,7 +1888,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probere
+@@ -1898,7 +1898,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probere
mgmt_frame = (u8 *)(rxframe + 1);
mgmt_frame_len = e->datalen - sizeof(*rxframe);
diff --git a/package/kernel/mac80211/patches/351-0008-brcmfmac-support-get_channel-cfg80211-callback.patch b/package/kernel/mac80211/patches/351-0008-brcmfmac-support-get_channel-cfg80211-callback.patch
index 3344e05af8..2c536d178d 100644
--- a/package/kernel/mac80211/patches/351-0008-brcmfmac-support-get_channel-cfg80211-callback.patch
+++ b/package/kernel/mac80211/patches/351-0008-brcmfmac-support-get_channel-cfg80211-callback.patch
@@ -15,7 +15,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -4769,6 +4769,68 @@ exit:
+@@ -4847,6 +4847,68 @@ exit:
return err;
}
@@ -84,7 +84,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
static int brcmf_cfg80211_crit_proto_start(struct wiphy *wiphy,
struct wireless_dev *wdev,
enum nl80211_crit_proto_id proto,
-@@ -4906,6 +4968,7 @@ static struct cfg80211_ops wl_cfg80211_o
+@@ -5009,6 +5071,7 @@ static struct cfg80211_ops brcmf_cfg8021
.mgmt_tx = brcmf_cfg80211_mgmt_tx,
.remain_on_channel = brcmf_p2p_remain_on_channel,
.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
diff --git a/package/kernel/mac80211/patches/351-0009-brcmfmac-print-errors-if-creating-interface-fails.patch b/package/kernel/mac80211/patches/351-0009-brcmfmac-print-errors-if-creating-interface-fails.patch
index 460baa64bd..1b119b2c85 100644
--- a/package/kernel/mac80211/patches/351-0009-brcmfmac-print-errors-if-creating-interface-fails.patch
+++ b/package/kernel/mac80211/patches/351-0009-brcmfmac-print-errors-if-creating-interface-fails.patch
@@ -15,7 +15,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -649,20 +649,24 @@ static struct wireless_dev *brcmf_cfg802
+@@ -670,20 +670,24 @@ static struct wireless_dev *brcmf_cfg802
return ERR_PTR(-EOPNOTSUPP);
case NL80211_IFTYPE_AP:
wdev = brcmf_ap_add_vif(wiphy, name, flags, params);
@@ -48,7 +48,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-@@ -2020,8 +2020,6 @@ static int brcmf_p2p_request_p2p_if(stru
+@@ -2030,8 +2030,6 @@ static int brcmf_p2p_request_p2p_if(stru
err = brcmf_fil_iovar_data_set(ifp, "p2p_ifadd", &if_request,
sizeof(if_request));
diff --git a/package/kernel/mac80211/patches/351-0010-brcmfmac-fix-setting-AP-channel-with-new-firmwares.patch b/package/kernel/mac80211/patches/351-0010-brcmfmac-fix-setting-AP-channel-with-new-firmwares.patch
index 19f4ee1c18..a2e18a5fe9 100644
--- a/package/kernel/mac80211/patches/351-0010-brcmfmac-fix-setting-AP-channel-with-new-firmwares.patch
+++ b/package/kernel/mac80211/patches/351-0010-brcmfmac-fix-setting-AP-channel-with-new-firmwares.patch
@@ -32,7 +32,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -4304,7 +4304,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+@@ -4382,7 +4382,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
struct brcmf_join_params join_params;
enum nl80211_iftype dev_role;
struct brcmf_fil_bss_enable_le bss_enable;
@@ -41,7 +41,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
bool mbss;
int is_11d;
-@@ -4380,16 +4380,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+@@ -4458,16 +4458,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
@@ -59,7 +59,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
if (is_11d != ifp->vif->is_11d) {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
is_11d);
-@@ -4437,6 +4429,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+@@ -4515,6 +4507,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
err = -EINVAL;
goto exit;
}
@@ -68,7 +68,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
if (dev_role == NL80211_IFTYPE_AP) {
if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss))
brcmf_fil_iovar_int_set(ifp, "mbss", 1);
-@@ -4446,6 +4440,17 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+@@ -4524,6 +4518,17 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
brcmf_err("setting AP mode failed %d\n", err);
goto exit;
}
@@ -86,7 +86,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
if (err < 0) {
brcmf_err("BRCMF_C_UP error (%d)\n", err);
-@@ -4467,7 +4472,13 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+@@ -4545,7 +4550,13 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
goto exit;
}
brcmf_dbg(TRACE, "AP mode configuration complete\n");
@@ -101,7 +101,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le,
sizeof(ssid_le));
if (err < 0) {
-@@ -4484,7 +4495,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+@@ -4562,7 +4573,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
}
brcmf_dbg(TRACE, "GO mode configuration complete\n");
diff --git a/package/kernel/mac80211/patches/351-0011-brcmfmac-don-t-remove-interface-on-link-down-firmwar.patch b/package/kernel/mac80211/patches/351-0011-brcmfmac-don-t-remove-interface-on-link-down-firmwar.patch
index df707a788f..167e4347d5 100644
--- a/package/kernel/mac80211/patches/351-0011-brcmfmac-don-t-remove-interface-on-link-down-firmwar.patch
+++ b/package/kernel/mac80211/patches/351-0011-brcmfmac-don-t-remove-interface-on-link-down-firmwar.patch
@@ -41,7 +41,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -5269,7 +5269,6 @@ brcmf_notify_connect_status_ap(struct br
+@@ -5372,7 +5372,6 @@ brcmf_notify_connect_status_ap(struct br
struct net_device *ndev,
const struct brcmf_event_msg *e, void *data)
{
@@ -49,7 +49,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
static int generation;
u32 event = e->event_code;
u32 reason = e->reason;
-@@ -5280,8 +5279,6 @@ brcmf_notify_connect_status_ap(struct br
+@@ -5383,8 +5382,6 @@ brcmf_notify_connect_status_ap(struct br
ndev != cfg_to_ndev(cfg)) {
brcmf_dbg(CONN, "AP mode link down\n");
complete(&cfg->vif_disabled);
diff --git a/package/kernel/mac80211/patches/351-0017-brcmfmac-drop-unused-pm_block-vif-attribute.patch b/package/kernel/mac80211/patches/351-0017-brcmfmac-drop-unused-pm_block-vif-attribute.patch
new file mode 100644
index 0000000000..28ef3a65fd
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0017-brcmfmac-drop-unused-pm_block-vif-attribute.patch
@@ -0,0 +1,103 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Mon, 6 Jun 2016 23:03:55 +0200
+Subject: [PATCH] brcmfmac: drop unused pm_block vif attribute
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This attribute was added 3 years ago by
+commit 3eacf866559c ("brcmfmac: introduce brcmf_cfg80211_vif structure")
+but it remains unused since then. It seems we can safely drop it.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -587,7 +587,7 @@ struct wireless_dev *brcmf_ap_add_vif(st
+
+ brcmf_dbg(INFO, "Adding vif \"%s\"\n", name);
+
+- vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_AP, false);
++ vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_AP);
+ if (IS_ERR(vif))
+ return (struct wireless_dev *)vif;
+
+@@ -5098,8 +5098,7 @@ static struct cfg80211_ops brcmf_cfg8021
+ };
+
+ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
+- enum nl80211_iftype type,
+- bool pm_block)
++ enum nl80211_iftype type)
+ {
+ struct brcmf_cfg80211_vif *vif_walk;
+ struct brcmf_cfg80211_vif *vif;
+@@ -5114,8 +5113,6 @@ struct brcmf_cfg80211_vif *brcmf_alloc_v
+ vif->wdev.wiphy = cfg->wiphy;
+ vif->wdev.iftype = type;
+
+- vif->pm_block = pm_block;
+-
+ brcmf_init_prof(&vif->profile);
+
+ if (type == NL80211_IFTYPE_AP) {
+@@ -6754,7 +6751,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+ init_vif_event(&cfg->vif_event);
+ INIT_LIST_HEAD(&cfg->vif_list);
+
+- vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
++ vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION);
+ if (IS_ERR(vif))
+ goto wiphy_out;
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -167,7 +167,6 @@ struct vif_saved_ie {
+ * @wdev: wireless device.
+ * @profile: profile information.
+ * @sme_state: SME state using enum brcmf_vif_status bits.
+- * @pm_block: power-management blocked.
+ * @list: linked list.
+ * @mgmt_rx_reg: registered rx mgmt frame types.
+ * @mbss: Multiple BSS type, set if not first AP (not relevant for P2P).
+@@ -177,7 +176,6 @@ struct brcmf_cfg80211_vif {
+ struct wireless_dev wdev;
+ struct brcmf_cfg80211_profile profile;
+ unsigned long sme_state;
+- bool pm_block;
+ struct vif_saved_ie saved_ie;
+ struct list_head list;
+ u16 mgmt_rx_reg;
+@@ -388,8 +386,7 @@ s32 brcmf_cfg80211_down(struct net_devic
+ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
+
+ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
+- enum nl80211_iftype type,
+- bool pm_block);
++ enum nl80211_iftype type);
+ void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
+
+ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+@@ -2074,8 +2074,7 @@ static struct wireless_dev *brcmf_p2p_cr
+ if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
+ return ERR_PTR(-ENOSPC);
+
+- p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE,
+- false);
++ p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE);
+ if (IS_ERR(p2p_vif)) {
+ brcmf_err("could not create discovery vif\n");
+ return (struct wireless_dev *)p2p_vif;
+@@ -2175,7 +2174,7 @@ struct wireless_dev *brcmf_p2p_add_vif(s
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+
+- vif = brcmf_alloc_vif(cfg, type, false);
++ vif = brcmf_alloc_vif(cfg, type);
+ if (IS_ERR(vif))
+ return (struct wireless_dev *)vif;
+ brcmf_cfg80211_arm_vif_event(cfg, vif);
diff --git a/package/kernel/mac80211/patches/351-0018-brcmfmac-include-required-headers-in-cfg80211.h.patch b/package/kernel/mac80211/patches/351-0018-brcmfmac-include-required-headers-in-cfg80211.h.patch
new file mode 100644
index 0000000000..09547d8d3b
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0018-brcmfmac-include-required-headers-in-cfg80211.h.patch
@@ -0,0 +1,37 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Tue, 7 Jun 2016 08:20:21 +0200
+Subject: [PATCH] brcmfmac: include required headers in cfg80211.h
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Without this including cfg80211.h in a wrong order could result in:
+
+drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:122:24: error: array type has incomplete element type
+ struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
+ ^
+drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:291:24: error: field ‘p2p’ has incomplete type
+ struct brcmf_p2p_info p2p;
+ ^
+drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:297:27: error: field ‘pmk_list’ has incomplete type
+ struct brcmf_pmk_list_le pmk_list;
+ ^
+drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:317:28: error: field ‘assoclist’ has incomplete type
+ struct brcmf_assoclist_le assoclist;
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -20,6 +20,9 @@
+ /* for brcmu_d11inf */
+ #include <brcmu_d11.h>
+
++#include "fwil_types.h"
++#include "p2p.h"
++
+ #define WL_NUM_SCAN_MAX 10
+ #define WL_TLV_INFO_MAX 1024
+ #define WL_BSS_INFO_MAX 2048
diff --git a/package/kernel/mac80211/patches/351-0019-brcmfmac-slightly-simplify-building-interface-combin.patch b/package/kernel/mac80211/patches/351-0019-brcmfmac-slightly-simplify-building-interface-combin.patch
new file mode 100644
index 0000000000..461e3dba53
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0019-brcmfmac-slightly-simplify-building-interface-combin.patch
@@ -0,0 +1,108 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Tue, 7 Jun 2016 21:10:18 +0200
+Subject: [PATCH] brcmfmac: slightly simplify building interface combinations
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This change reorders some operations in brcmf_setup_ifmodes in hope to
+make it simpler:
+1) It allocates arrays right before filling them. This way it's easier
+ to follow requested array length as it's immediately followed by
+ code filling it. It's easier to check e.g. why we need 4 entries for
+ P2P. Other than that it deduplicates some checks (e.g. for P2P).
+2) It reorders code to first prepare limits and then define a new combo.
+ Previously this was mixed (e.g. we were setting num of channels
+ before preparing limits).
+3) It modifies mbss code to use i variable just like other combos do.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -6208,29 +6208,15 @@ static int brcmf_setup_ifmodes(struct wi
+ if (!combo)
+ goto err;
+
+- 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);
+
+ c = 0;
+ i = 0;
+- combo[c].num_different_channels = 1;
++ c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL);
++ if (!c0_limits)
++ goto err;
+ c0_limits[i].max = 1;
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+ if (p2p) {
+@@ -6248,6 +6234,7 @@ static int brcmf_setup_ifmodes(struct wi
+ c0_limits[i].max = 1;
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+ }
++ combo[c].num_different_channels = 1;
+ combo[c].max_interfaces = i;
+ combo[c].n_limits = i;
+ combo[c].limits = c0_limits;
+@@ -6255,7 +6242,9 @@ static int brcmf_setup_ifmodes(struct wi
+ if (p2p) {
+ c++;
+ i = 0;
+- combo[c].num_different_channels = 1;
++ p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL);
++ if (!p2p_limits)
++ goto err;
+ p2p_limits[i].max = 1;
+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+ p2p_limits[i].max = 1;
+@@ -6264,6 +6253,7 @@ static int brcmf_setup_ifmodes(struct wi
+ 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].num_different_channels = 1;
+ combo[c].max_interfaces = i;
+ combo[c].n_limits = i;
+ combo[c].limits = p2p_limits;
+@@ -6271,14 +6261,19 @@ static int brcmf_setup_ifmodes(struct wi
+
+ if (mbss) {
+ c++;
++ i = 0;
++ mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL);
++ if (!mbss_limits)
++ goto err;
++ mbss_limits[i].max = 4;
++ mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+ 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].n_limits = i;
+ combo[c].limits = mbss_limits;
+ }
++
+ wiphy->n_iface_combinations = n_combos;
+ wiphy->iface_combinations = combo;
+ return 0;
diff --git a/package/kernel/mac80211/patches/351-0020-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch b/package/kernel/mac80211/patches/351-0020-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch
new file mode 100644
index 0000000000..e991f32327
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0020-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch
@@ -0,0 +1,160 @@
+From b50ddfa8530e9b5f52e873fdd6ff04f327a88799 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Fri, 17 Jun 2016 12:29:21 +0200
+Subject: [PATCH] brcmfmac: fix lockup when removing P2P interface after event
+ timeout
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Removing P2P interface is handled by sending a proper request to the
+firmware. On success firmware triggers an event and driver's handler
+removes a matching interface.
+
+However on event timeout we remove interface directly from the cfg80211
+callback. Current code doesn't handle this case correctly as it always
+assumes rtnl to be unlocked.
+
+Fix it by adding an extra rtnl_locked parameter to functions and calling
+unregister_netdevice when needed.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../wireless/broadcom/brcm80211/brcmfmac/core.c | 29 +++++++++++++---------
+ .../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 +-
+ .../wireless/broadcom/brcm80211/brcmfmac/fweh.c | 2 +-
+ .../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 4 +--
+ 4 files changed, 21 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -548,12 +548,16 @@ fail:
+ return -EBADE;
+ }
+
+-static void brcmf_net_detach(struct net_device *ndev)
++static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked)
+ {
+- if (ndev->reg_state == NETREG_REGISTERED)
+- unregister_netdev(ndev);
+- else
++ if (ndev->reg_state == NETREG_REGISTERED) {
++ if (rtnl_locked)
++ unregister_netdevice(ndev);
++ else
++ unregister_netdev(ndev);
++ } else {
+ brcmf_cfg80211_free_netdev(ndev);
++ }
+ }
+
+ void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
+@@ -651,7 +655,7 @@ struct brcmf_if *brcmf_add_if(struct brc
+ brcmf_err("ERROR: netdev:%s already exists\n",
+ ifp->ndev->name);
+ netif_stop_queue(ifp->ndev);
+- brcmf_net_detach(ifp->ndev);
++ brcmf_net_detach(ifp->ndev, false);
+ drvr->iflist[bsscfgidx] = NULL;
+ } else {
+ brcmf_dbg(INFO, "netdev:%s ignore IF event\n",
+@@ -699,7 +703,8 @@ struct brcmf_if *brcmf_add_if(struct brc
+ return ifp;
+ }
+
+-static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx)
++static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx,
++ bool rtnl_locked)
+ {
+ struct brcmf_if *ifp;
+
+@@ -729,7 +734,7 @@ static void brcmf_del_if(struct brcmf_pu
+ cancel_work_sync(&ifp->multicast_work);
+ cancel_work_sync(&ifp->ndoffload_work);
+ }
+- brcmf_net_detach(ifp->ndev);
++ brcmf_net_detach(ifp->ndev, rtnl_locked);
+ } else {
+ /* Only p2p device interfaces which get dynamically created
+ * end up here. In this case the p2p module should be informed
+@@ -743,14 +748,14 @@ static void brcmf_del_if(struct brcmf_pu
+ }
+ }
+
+-void brcmf_remove_interface(struct brcmf_if *ifp)
++void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked)
+ {
+ if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp))
+ return;
+ brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", ifp->bsscfgidx,
+ ifp->ifidx);
+ brcmf_fws_del_interface(ifp);
+- brcmf_del_if(ifp->drvr, ifp->bsscfgidx);
++ brcmf_del_if(ifp->drvr, ifp->bsscfgidx, rtnl_locked);
+ }
+
+ #ifdef CONFIG_INET
+@@ -1057,9 +1062,9 @@ fail:
+ brcmf_fws_deinit(drvr);
+ }
+ if (ifp)
+- brcmf_net_detach(ifp->ndev);
++ brcmf_net_detach(ifp->ndev, false);
+ if (p2p_ifp)
+- brcmf_net_detach(p2p_ifp->ndev);
++ brcmf_net_detach(p2p_ifp->ndev, false);
+ drvr->iflist[0] = NULL;
+ drvr->iflist[1] = NULL;
+ if (drvr->settings->ignore_probe_fail)
+@@ -1128,7 +1133,7 @@ void brcmf_detach(struct device *dev)
+
+ /* make sure primary interface removed last */
+ for (i = BRCMF_MAX_IFS-1; i > -1; i--)
+- brcmf_remove_interface(drvr->iflist[i]);
++ brcmf_remove_interface(drvr->iflist[i], false);
+
+ brcmf_cfg80211_detach(drvr->config);
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -216,7 +216,7 @@ struct brcmf_if *brcmf_get_ifp(struct br
+ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
+ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
+ bool is_p2pdev, char *name, u8 *mac_addr);
+-void brcmf_remove_interface(struct brcmf_if *ifp);
++void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked);
+ void brcmf_txflowblock_if(struct brcmf_if *ifp,
+ enum brcmf_netif_stop_reason reason, bool state);
+ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+@@ -183,7 +183,7 @@ static void brcmf_fweh_handle_if_event(s
+ err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
+
+ if (ifp && ifevent->action == BRCMF_E_IF_DEL)
+- brcmf_remove_interface(ifp);
++ brcmf_remove_interface(ifp, false);
+ }
+
+ /**
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+@@ -2289,7 +2289,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+ err = 0;
+ }
+ if (err)
+- brcmf_remove_interface(vif->ifp);
++ brcmf_remove_interface(vif->ifp, true);
+
+ brcmf_cfg80211_arm_vif_event(cfg, NULL);
+ if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
+@@ -2395,7 +2395,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_i
+ if (vif != NULL) {
+ brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+ brcmf_p2p_deinit_discovery(p2p);
+- brcmf_remove_interface(vif->ifp);
++ brcmf_remove_interface(vif->ifp, false);
+ }
+ /* just set it all to zero */
+ memset(p2p, 0, sizeof(*p2p));
diff --git a/package/kernel/mac80211/patches/351-0021-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch b/package/kernel/mac80211/patches/351-0021-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch
new file mode 100644
index 0000000000..ed65f4dc88
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0021-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch
@@ -0,0 +1,39 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Fri, 17 Jun 2016 12:48:44 +0200
+Subject: [PATCH] brcmfmac: use const char * for interface name in brcmf_add_if
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This function can work just fine with const pointer, it only calls
+alloc_netdev which take const as well. Moreover it makes this function
+more flexible as some cfg80211 callback may provide const char * as
+well, e.g. add_virtual_intf. This will be needed for more advanced
+interface management.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -638,7 +638,7 @@ fail:
+ }
+
+ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
+- bool is_p2pdev, char *name, u8 *mac_addr)
++ bool is_p2pdev, const char *name, u8 *mac_addr)
+ {
+ struct brcmf_if *ifp;
+ struct net_device *ndev;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -215,7 +215,7 @@ char *brcmf_ifname(struct brcmf_if *ifp)
+ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
+ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
+ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
+- bool is_p2pdev, char *name, u8 *mac_addr);
++ bool is_p2pdev, const char *name, u8 *mac_addr);
+ void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked);
+ void brcmf_txflowblock_if(struct brcmf_if *ifp,
+ enum brcmf_netif_stop_reason reason, bool state);
diff --git a/package/kernel/mac80211/patches/351-0022-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch b/package/kernel/mac80211/patches/351-0022-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch
new file mode 100644
index 0000000000..ef35fab7d7
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0022-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch
@@ -0,0 +1,33 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sat, 18 Jun 2016 18:49:38 +0200
+Subject: [PATCH] brcmfmac: include also core.h header in cfg80211.h
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This header provides two inline functions using struct brcmf_if so we
+need core.h to avoid:
+
+drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h: In function ‘ndev_to_prof’:
+drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:368:13: error: dereferencing pointer to incomplete type
+ return &ifp->vif->profile;
+ ^
+drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h: In function ‘ndev_to_vif’:
+drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:374:12: error: dereferencing pointer to incomplete type
+ return ifp->vif;
+ ^
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -20,6 +20,7 @@
+ /* for brcmu_d11inf */
+ #include <brcmu_d11.h>
+
++#include "core.h"
+ #include "fwil_types.h"
+ #include "p2p.h"
+
diff --git a/package/kernel/mac80211/patches/351-0023-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch b/package/kernel/mac80211/patches/351-0023-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch
new file mode 100644
index 0000000000..ab9a634437
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0023-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch
@@ -0,0 +1,27 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sun, 19 Jun 2016 01:55:57 +0200
+Subject: [PATCH] brcmfmac: add missing break when deleting P2P_DEVICE
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We obviously don't want to fall through in that switch. With this change
+1) We wait for event (triggered by p2p_disc) as expected
+2) We remove interface manually on timeout
+3) We return 0 on success instead of -ENOTSUPP
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+@@ -2263,6 +2263,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+ return 0;
+ brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+ brcmf_p2p_deinit_discovery(p2p);
++ break;
++
+ default:
+ return -ENOTSUPP;
+ }
diff --git a/package/kernel/mac80211/patches/351-0024-brcmfmac-delete-interface-directly-in-code-that-sent.patch b/package/kernel/mac80211/patches/351-0024-brcmfmac-delete-interface-directly-in-code-that-sent.patch
new file mode 100644
index 0000000000..6dd0c03e3d
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0024-brcmfmac-delete-interface-directly-in-code-that-sent.patch
@@ -0,0 +1,75 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 29 Jun 2016 21:54:26 +0200
+Subject: [PATCH] brcmfmac: delete interface directly in code that sent fw
+ request
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+So far when receiving event about in-firmware-interface removal our
+event worker was notifying listener and afterwards it was removing Linux
+interface.
+
+First of all it was resulting in slightly unexpected order. The listener
+(del_virtual_intf callback) was (usually) returning with success before
+we even called unregister_netdev(ice).
+
+Please note this couldn't be simply fixed by changing order of calls in
+brcmf_fweh_handle_if_event as unregistering interface earlier could free
+struct brcmf_if.
+
+Another problem of current implementation are possible lockups. Focus on
+the time slot between calling event handler and removing Linux
+interface. During that time original caller may leave (unlocking rtnl
+semaphore) *and* another call to the same code may be done (locking it
+again). If that happens our event handler will stuck at removing Linux
+interface, it won't handle another event and will block process holding
+rtnl lock.
+
+This can be simply solved by unregistering interface in a proper
+callback, right after receiving confirmation event from firmware. This
+only required modifying worker to don't unregister on its own if there
+is someone waiting for the event.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+@@ -18,6 +18,7 @@
+ #include "brcmu_wifi.h"
+ #include "brcmu_utils.h"
+
++#include "cfg80211.h"
+ #include "core.h"
+ #include "debug.h"
+ #include "tracepoint.h"
+@@ -182,8 +183,13 @@ static void brcmf_fweh_handle_if_event(s
+
+ err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
+
+- if (ifp && ifevent->action == BRCMF_E_IF_DEL)
+- brcmf_remove_interface(ifp, false);
++ if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
++ bool armed = brcmf_cfg80211_vif_event_armed(drvr->config);
++
++ /* Default handling in case no-one waits for this event */
++ if (!armed)
++ brcmf_remove_interface(ifp, false);
++ }
+ }
+
+ /**
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+@@ -2290,8 +2290,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+ else
+ err = 0;
+ }
+- if (err)
+- brcmf_remove_interface(vif->ifp, true);
++ brcmf_remove_interface(vif->ifp, true);
+
+ brcmf_cfg80211_arm_vif_event(cfg, NULL);
+ if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
diff --git a/package/kernel/mac80211/patches/351-0025-brcmfmac-support-removing-AP-interfaces-with-interfa.patch b/package/kernel/mac80211/patches/351-0025-brcmfmac-support-removing-AP-interfaces-with-interfa.patch
new file mode 100644
index 0000000000..1929f0b812
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0025-brcmfmac-support-removing-AP-interfaces-with-interfa.patch
@@ -0,0 +1,84 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 29 Jun 2016 21:54:27 +0200
+Subject: [PATCH] brcmfmac: support removing AP interfaces with
+ "interface_remove"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+New firmwares (e.g. 10.10.69.36 for BCM4366) support "interface_remove"
+for removing interfaces. Try to use this method on cfg80211 request. In
+case of older firmwares (e.g. 7.35.177.56 for BCM43602 as I tested) this
+will just result in firmware rejecting command and this won't change any
+behavior.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -771,12 +771,48 @@ s32 brcmf_notify_escan_complete(struct b
+ return err;
+ }
+
++static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
++ struct wireless_dev *wdev)
++{
++ struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
++ struct net_device *ndev = wdev->netdev;
++ struct brcmf_if *ifp = netdev_priv(ndev);
++ int ret;
++ int err;
++
++ brcmf_cfg80211_arm_vif_event(cfg, ifp->vif);
++
++ err = brcmf_fil_bsscfg_data_set(ifp, "interface_remove", NULL, 0);
++ if (err) {
++ brcmf_err("interface_remove failed %d\n", err);
++ goto err_unarm;
++ }
++
++ /* wait for firmware event */
++ ret = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL,
++ BRCMF_VIF_EVENT_TIMEOUT);
++ if (!ret) {
++ brcmf_err("timeout occurred\n");
++ err = -EIO;
++ goto err_unarm;
++ }
++
++ brcmf_remove_interface(ifp, true);
++
++err_unarm:
++ brcmf_cfg80211_arm_vif_event(cfg, NULL);
++ return err;
++}
++
+ static
+ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
+ {
+ struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
+ struct net_device *ndev = wdev->netdev;
+
++ if (ndev && ndev == cfg_to_ndev(cfg))
++ return -ENOTSUPP;
++
+ /* vif event pending in firmware */
+ if (brcmf_cfg80211_vif_event_armed(cfg))
+ return -EBUSY;
+@@ -793,12 +829,13 @@ int brcmf_cfg80211_del_iface(struct wiph
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_STATION:
+- case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_MESH_POINT:
+ return -EOPNOTSUPP;
++ case NL80211_IFTYPE_AP:
++ return brcmf_cfg80211_del_ap_iface(wiphy, wdev);
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_P2P_GO:
+ case NL80211_IFTYPE_P2P_DEVICE:
diff --git a/package/kernel/mac80211/patches/351-0026-brcmfmac-respect-hidden_ssid-for-AP-interfaces.patch b/package/kernel/mac80211/patches/351-0026-brcmfmac-respect-hidden_ssid-for-AP-interfaces.patch
new file mode 100644
index 0000000000..ae458e7a02
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0026-brcmfmac-respect-hidden_ssid-for-AP-interfaces.patch
@@ -0,0 +1,43 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 6 Jul 2016 12:22:54 +0200
+Subject: [PATCH] brcmfmac: respect hidden_ssid for AP interfaces
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This was succesfully tested with 4366B1. A small workaround is needed
+for the main interface otherwise it would stuck at the hidden state.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -4586,6 +4586,15 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+ brcmf_err("SET SSID error (%d)\n", err);
+ goto exit;
+ }
++
++ if (settings->hidden_ssid) {
++ err = brcmf_fil_iovar_int_set(ifp, "closednet", 1);
++ if (err) {
++ brcmf_err("closednet error (%d)\n", err);
++ goto exit;
++ }
++ }
++
+ brcmf_dbg(TRACE, "AP mode configuration complete\n");
+ } else if (dev_role == NL80211_IFTYPE_P2P_GO) {
+ err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
+@@ -4644,6 +4653,10 @@ static int brcmf_cfg80211_stop_ap(struct
+ return err;
+ }
+
++ /* First BSS doesn't get a full reset */
++ if (ifp->bsscfgidx == 0)
++ brcmf_fil_iovar_int_set(ifp, "closednet", 0);
++
+ memset(&join_params, 0, sizeof(join_params));
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+ &join_params, sizeof(join_params));
diff --git a/package/kernel/mac80211/patches/351-0027-brcmfmac-restore-stopping-netdev-queue-when-bus-clog.patch b/package/kernel/mac80211/patches/351-0027-brcmfmac-restore-stopping-netdev-queue-when-bus-clog.patch
new file mode 100644
index 0000000000..fcafa797ef
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0027-brcmfmac-restore-stopping-netdev-queue-when-bus-clog.patch
@@ -0,0 +1,53 @@
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Fri, 15 Jul 2016 12:16:12 +0200
+Subject: [PATCH] brcmfmac: restore stopping netdev queue when bus clogs up
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When the host-interface bus has hard time handling transmit packets
+it informs higher layer about this and it would stop the netdev
+queue when needed. However, since commit 9cd18359d31e ("brcmfmac:
+Make FWS queueing configurable.") this was broken. With this patch
+the behaviour is restored.
+
+Cc: stable@vger.kernel.org # v4.5, v4.6, v4.7
+Fixes: 9cd18359d31e ("brcmfmac: Make FWS queueing configurable.")
+Tested-by: Per Förlin <per.forlin@gmail.com>
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+@@ -2469,10 +2469,22 @@ void brcmf_fws_bustxfail(struct brcmf_fw
+ void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked)
+ {
+ struct brcmf_fws_info *fws = drvr->fws;
++ struct brcmf_if *ifp;
++ int i;
+
+- fws->bus_flow_blocked = flow_blocked;
+- if (!flow_blocked)
+- brcmf_fws_schedule_deq(fws);
+- else
+- fws->stats.bus_flow_block++;
++ if (fws->avoid_queueing) {
++ for (i = 0; i < BRCMF_MAX_IFS; i++) {
++ ifp = drvr->iflist[i];
++ if (!ifp || !ifp->ndev)
++ continue;
++ brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW,
++ flow_blocked);
++ }
++ } else {
++ fws->bus_flow_blocked = flow_blocked;
++ if (!flow_blocked)
++ brcmf_fws_schedule_deq(fws);
++ else
++ fws->stats.bus_flow_block++;
++ }
+ }
diff --git a/package/kernel/mac80211/patches/351-0028-brcmfmac-defer-DPC-processing-during-probe.patch b/package/kernel/mac80211/patches/351-0028-brcmfmac-defer-DPC-processing-during-probe.patch
new file mode 100644
index 0000000000..a24c07f973
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0028-brcmfmac-defer-DPC-processing-during-probe.patch
@@ -0,0 +1,42 @@
+From fd3ed33f51c2a586412d35b4f64803f019ab589f Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Fri, 15 Jul 2016 12:39:13 +0200
+Subject: [PATCH] brcmfmac: defer DPC processing during probe
+
+The sdio dpc starts processing when in SDIOD_STATE_DATA. This state was
+entered right after firmware download. This patch moves that transition
+just before enabling sdio interrupt handling thus avoiding watchdog
+expiry which would put the bus to sleep while probing.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -3304,10 +3304,6 @@ static int brcmf_sdio_download_firmware(
+ goto err;
+ }
+
+- /* Allow full data communication using DPC from now on. */
+- brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
+- bcmerror = 0;
+-
+ err:
+ brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
+ sdio_release_host(bus->sdiodev->func[1]);
+@@ -4045,6 +4041,9 @@ static void brcmf_sdio_firmware_callback
+ }
+
+ if (err == 0) {
++ /* Allow full data communication using DPC from now on. */
++ brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
++
+ err = brcmf_sdiod_intr_register(sdiodev);
+ if (err != 0)
+ brcmf_err("intr register failed:%d\n", err);
diff --git a/package/kernel/mac80211/patches/351-0029-brcmfmac-Fix-glob_skb-leak-in-brcmf_sdiod_recv_chain.patch b/package/kernel/mac80211/patches/351-0029-brcmfmac-Fix-glob_skb-leak-in-brcmf_sdiod_recv_chain.patch
new file mode 100644
index 0000000000..ba9a349f0f
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0029-brcmfmac-Fix-glob_skb-leak-in-brcmf_sdiod_recv_chain.patch
@@ -0,0 +1,32 @@
+From 3bdae810721b33061d2e541bd78a70f86ca42af3 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <f.fainelli@gmail.com>
+Date: Mon, 18 Jul 2016 16:24:34 -0700
+Subject: [PATCH] brcmfmac: Fix glob_skb leak in brcmf_sdiod_recv_chain
+
+In case brcmf_sdiod_recv_chain() cannot complete a succeful call to
+brcmf_sdiod_buffrw, we would be leaking glom_skb and not free it as we
+should, fix this.
+
+Reported-by: coverity (CID 1164856)
+Fixes: a413e39a38573 ("brcmfmac: fix brcmf_sdcard_recv_chain() for host without sg support")
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -722,8 +722,10 @@ int brcmf_sdiod_recv_chain(struct brcmf_
+ return -ENOMEM;
+ err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
+ glom_skb);
+- if (err)
++ if (err) {
++ brcmu_pkt_buf_free_skb(glom_skb);
+ goto done;
++ }
+
+ skb_queue_walk(pktq, skb) {
+ memcpy(skb->data, glom_skb->data, skb->len);
diff --git a/package/kernel/mac80211/patches/351-0030-net-wireless-broadcom-brcm80211-brcmfmac-usb-don-t-p.patch b/package/kernel/mac80211/patches/351-0030-net-wireless-broadcom-brcm80211-brcmfmac-usb-don-t-p.patch
new file mode 100644
index 0000000000..540b7f08bf
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0030-net-wireless-broadcom-brcm80211-brcmfmac-usb-don-t-p.patch
@@ -0,0 +1,34 @@
+From 938f89e50a41c2d56710805fb019ad7618cef84b Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa-dev@sang-engineering.com>
+Date: Thu, 11 Aug 2016 23:05:31 +0200
+Subject: [PATCH] net: wireless: broadcom: brcm80211: brcmfmac: usb: don't
+ print error when allocating urb fails
+
+kmalloc will print enough information in case of failure.
+
+Signed-off-by: Wolfram Sang <wsa-dev@sang-engineering.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+@@ -1099,15 +1099,11 @@ struct brcmf_usbdev *brcmf_usb_attach(st
+ devinfo->tx_freecount = ntxq;
+
+ devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC);
+- if (!devinfo->ctl_urb) {
+- brcmf_err("usb_alloc_urb (ctl) failed\n");
++ if (!devinfo->ctl_urb)
+ goto error;
+- }
+ devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC);
+- if (!devinfo->bulk_urb) {
+- brcmf_err("usb_alloc_urb (bulk) failed\n");
++ if (!devinfo->bulk_urb)
+ goto error;
+- }
+
+ return &devinfo->bus_pub;
+
diff --git a/package/kernel/mac80211/patches/351-0031-brcmfmac-Check-rtnl_lock-is-locked-when-removing-int.patch b/package/kernel/mac80211/patches/351-0031-brcmfmac-Check-rtnl_lock-is-locked-when-removing-int.patch
new file mode 100644
index 0000000000..b98b68a88a
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0031-brcmfmac-Check-rtnl_lock-is-locked-when-removing-int.patch
@@ -0,0 +1,111 @@
+From 15dacf880e49ce3ecee05eb1a0c6b8e363dbacdc Mon Sep 17 00:00:00 2001
+From: "mhiramat@kernel.org" <mhiramat@kernel.org>
+Date: Mon, 15 Aug 2016 18:40:57 +0900
+Subject: [PATCH] brcmfmac: Check rtnl_lock is locked when removing interface
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Check rtnl_lock is locked in brcmf_p2p_ifp_removed() by passing
+rtnl_locked flag. Actually the caller brcmf_del_if() checks whether
+the rtnl_lock is locked, but doesn't pass it to brcmf_p2p_ifp_removed().
+
+Without this fix, wpa_supplicant goes softlockup with rtnl_lock
+holding (this means all other process using netlink are locked up too)
+
+e.g.
+[ 4495.876627] INFO: task wpa_supplicant:7307 blocked for more than 10 seconds.
+[ 4495.876632] Tainted: G W 4.8.0-rc1+ #8
+[ 4495.876635] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+[ 4495.876638] wpa_supplicant D ffff974c647b39a0 0 7307 1 0x00000000
+[ 4495.876644] ffff974c647b39a0 0000000000000000 ffff974c00000000 ffff974c7dc59c58
+[ 4495.876651] ffff974c6b7417c0 ffff974c645017c0 ffff974c647b4000 ffffffff86f16c08
+[ 4495.876657] ffff974c645017c0 0000000000000246 00000000ffffffff ffff974c647b39b8
+[ 4495.876664] Call Trace:
+[ 4495.876671] [<ffffffff868aeccc>] schedule+0x3c/0x90
+[ 4495.876676] [<ffffffff868af065>] schedule_preempt_disabled+0x15/0x20
+[ 4495.876682] [<ffffffff868b0996>] mutex_lock_nested+0x176/0x3b0
+[ 4495.876686] [<ffffffff867a2067>] ? rtnl_lock+0x17/0x20
+[ 4495.876690] [<ffffffff867a2067>] rtnl_lock+0x17/0x20
+[ 4495.876720] [<ffffffffc0ae9a5d>] brcmf_p2p_ifp_removed+0x4d/0x70 [brcmfmac]
+[ 4495.876741] [<ffffffffc0aebde6>] brcmf_remove_interface+0x196/0x1b0 [brcmfmac]
+[ 4495.876760] [<ffffffffc0ae9901>] brcmf_p2p_del_vif+0x111/0x220 [brcmfmac]
+[ 4495.876777] [<ffffffffc0adefab>] brcmf_cfg80211_del_iface+0x21b/0x270 [brcmfmac]
+[ 4495.876820] [<ffffffffc097b39e>] nl80211_del_interface+0xfe/0x3a0 [cfg80211]
+[ 4495.876825] [<ffffffff867ca335>] genl_family_rcv_msg+0x1b5/0x370
+[ 4495.876832] [<ffffffff860e5d8d>] ? trace_hardirqs_on+0xd/0x10
+[ 4495.876836] [<ffffffff867ca56d>] genl_rcv_msg+0x7d/0xb0
+[ 4495.876839] [<ffffffff867ca4f0>] ? genl_family_rcv_msg+0x370/0x370
+[ 4495.876846] [<ffffffff867c9a47>] netlink_rcv_skb+0x97/0xb0
+[ 4495.876849] [<ffffffff867ca168>] genl_rcv+0x28/0x40
+[ 4495.876854] [<ffffffff867c93c3>] netlink_unicast+0x1d3/0x2f0
+[ 4495.876860] [<ffffffff867c933b>] ? netlink_unicast+0x14b/0x2f0
+[ 4495.876866] [<ffffffff867c97cb>] netlink_sendmsg+0x2eb/0x3a0
+[ 4495.876870] [<ffffffff8676dad8>] sock_sendmsg+0x38/0x50
+[ 4495.876874] [<ffffffff8676e4df>] ___sys_sendmsg+0x27f/0x290
+[ 4495.876882] [<ffffffff8628b935>] ? mntput_no_expire+0x5/0x3f0
+[ 4495.876888] [<ffffffff8628b9be>] ? mntput_no_expire+0x8e/0x3f0
+[ 4495.876894] [<ffffffff8628b935>] ? mntput_no_expire+0x5/0x3f0
+[ 4495.876899] [<ffffffff8628bd44>] ? mntput+0x24/0x40
+[ 4495.876904] [<ffffffff86267830>] ? __fput+0x190/0x200
+[ 4495.876909] [<ffffffff8676f125>] __sys_sendmsg+0x45/0x80
+[ 4495.876914] [<ffffffff8676f172>] SyS_sendmsg+0x12/0x20
+[ 4495.876918] [<ffffffff868b5680>] entry_SYSCALL_64_fastpath+0x23/0xc1
+[ 4495.876924] [<ffffffff860e2b8f>] ? trace_hardirqs_off_caller+0x1f/0xc0
+
+Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
+Acked-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 2 +-
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 8 +++++---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h | 2 +-
+ 3 files changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -743,7 +743,7 @@ static void brcmf_del_if(struct brcmf_pu
+ * serious troublesome side effects. The p2p module will clean
+ * up the ifp if needed.
+ */
+- brcmf_p2p_ifp_removed(ifp);
++ brcmf_p2p_ifp_removed(ifp, rtnl_locked);
+ kfree(ifp);
+ }
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+@@ -2299,7 +2299,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+ return err;
+ }
+
+-void brcmf_p2p_ifp_removed(struct brcmf_if *ifp)
++void brcmf_p2p_ifp_removed(struct brcmf_if *ifp, bool rtnl_locked)
+ {
+ struct brcmf_cfg80211_info *cfg;
+ struct brcmf_cfg80211_vif *vif;
+@@ -2308,9 +2308,11 @@ void brcmf_p2p_ifp_removed(struct brcmf_
+ vif = ifp->vif;
+ cfg = wdev_to_cfg(&vif->wdev);
+ cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+- rtnl_lock();
++ if (!rtnl_locked)
++ rtnl_lock();
+ cfg80211_unregister_wdev(&vif->wdev);
+- rtnl_unlock();
++ if (!rtnl_locked)
++ rtnl_unlock();
+ brcmf_free_vif(vif);
+ }
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
+@@ -155,7 +155,7 @@ struct wireless_dev *brcmf_p2p_add_vif(s
+ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev);
+ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
+ enum brcmf_fil_p2p_if_types if_type);
+-void brcmf_p2p_ifp_removed(struct brcmf_if *ifp);
++void brcmf_p2p_ifp_removed(struct brcmf_if *ifp, bool rtnl_locked);
+ int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
diff --git a/package/kernel/mac80211/patches/351-0032-brcmfmac-Change-vif_event_lock-to-spinlock.patch b/package/kernel/mac80211/patches/351-0032-brcmfmac-Change-vif_event_lock-to-spinlock.patch
new file mode 100644
index 0000000000..30ca25897d
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0032-brcmfmac-Change-vif_event_lock-to-spinlock.patch
@@ -0,0 +1,175 @@
+From b64abcb7dae6060c67ab0e548da3ef923c49641d Mon Sep 17 00:00:00 2001
+From: "mhiramat@kernel.org" <mhiramat@kernel.org>
+Date: Mon, 15 Aug 2016 18:41:12 +0900
+Subject: [PATCH] brcmfmac: Change vif_event_lock to spinlock
+
+Change vif_event_lock to spinlock from mutex, since this lock is
+used in wait_event_timeout() via vif_event_equals(). This caused
+a warning report as below.
+
+As far as I can see, this lock protects regions where updating
+structure members, not function calls. Also, since those
+regions are not called from interrupt handlers (of course, it
+was a mutex), spin_lock is used instead of spin_lock_irqsave.
+
+[ 186.678550] ------------[ cut here ]------------
+[ 186.678556] WARNING: CPU: 2 PID: 7140 at /home/mhiramat/ksrc/linux/kernel/sched/core.c:7545 __might_sleep+0x7c/0x80
+[ 186.678560] do not call blocking ops when !TASK_RUNNING; state=2 set at [<ffffffff980d9090>] prepare_to_wait_event+0x60/0x100
+[ 186.678560] Modules linked in: brcmfmac xt_CHECKSUM rfcomm ipt_MASQUERADE nf_nat_masquerade_ipv4 xt_addrtype br_netfilter xt_tcpudp ip6t_rpfilter ip6t_REJECT nf_reject_ipv6 ipt_REJECT nf_reject_ipv4 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ebtable_filter ebtables ip6table_raw ip6table_security ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_filter ip6_tables iptable_raw iptable_security iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle iptable_filter ip_tables x_tables bnep nls_iso8859_1 i2c_designware_platform i2c_designware_core snd_hda_codec_hdmi snd_hda_codec_realtek dcdbas snd_hda_codec_generic snd_hda_intel snd_hda_codec intel_rapl snd_hda_core x86_pkg_temp_thermal intel_powerclamp coretemp
+[ 186.678594] snd_pcm crct10dif_pclmul crc32_pclmul aesni_intel aes_x86_64 joydev glue_helper snd_hwdep lrw gf128mul uvcvideo ablk_helper snd_seq_midi cryptd snd_seq_midi_event snd_rawmidi videobuf2_vmalloc videobuf2_memops snd_seq input_leds videobuf2_v4l2 cfg80211 videobuf2_core snd_timer videodev serio_raw btusb snd_seq_device media btrtl rtsx_pci_ms snd mei_me memstick hid_multitouch mei soundcore brcmutil idma64 virt_dma intel_lpss_pci processor_thermal_device intel_soc_dts_iosf hci_uart btbcm btqca btintel bluetooth int3403_thermal dell_smo8800 intel_lpss_acpi intel_lpss int3402_thermal int340x_thermal_zone intel_hid mac_hid int3400_thermal shpchp sparse_keymap acpi_pad acpi_thermal_rel acpi_als kfifo_buf industrialio kvm_intel kvm irqbypass parport_pc ppdev lp parport autofs4 btrfs xor raid6_pq
+[ 186.678631] usbhid nouveau ttm i915 rtsx_pci_sdmmc mxm_wmi i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops psmouse drm ahci rtsx_pci nvme nvme_core libahci i2c_hid hid pinctrl_sunrisepoint video wmi pinctrl_intel fjes [last unloaded: brcmfmac]
+[ 186.678646] CPU: 2 PID: 7140 Comm: wpa_supplicant Not tainted 4.8.0-rc1+ #8
+[ 186.678647] Hardware name: Dell Inc. XPS 15 9550/0N7TVV, BIOS 01.02.00 04/07/2016
+[ 186.678648] 0000000000000000 ffff9d8c64b5b900 ffffffff98442f23 ffff9d8c64b5b950
+[ 186.678651] 0000000000000000 ffff9d8c64b5b940 ffffffff9808b22b 00001d790000000d
+[ 186.678653] ffffffff98c75e78 000000000000026c 0000000000000000 ffff9d8c2706d058
+[ 186.678655] Call Trace:
+[ 186.678659] [<ffffffff98442f23>] dump_stack+0x85/0xc2
+[ 186.678666] [<ffffffff9808b22b>] __warn+0xcb/0xf0
+[ 186.678668] [<ffffffff9808b29f>] warn_slowpath_fmt+0x4f/0x60
+[ 186.678671] [<ffffffff980d9090>] ? prepare_to_wait_event+0x60/0x100
+[ 186.678672] [<ffffffff980d9090>] ? prepare_to_wait_event+0x60/0x100
+[ 186.678674] [<ffffffff980b922c>] __might_sleep+0x7c/0x80
+[ 186.678680] [<ffffffff988b0853>] mutex_lock_nested+0x33/0x3b0
+[ 186.678682] [<ffffffff980e5d8d>] ? trace_hardirqs_on+0xd/0x10
+[ 186.678689] [<ffffffffc0c57d2d>] brcmf_cfg80211_wait_vif_event+0xcd/0x130 [brcmfmac]
+[ 186.678691] [<ffffffff980d9190>] ? wake_atomic_t_function+0x60/0x60
+[ 186.678697] [<ffffffffc0c628e9>] brcmf_p2p_del_vif+0xf9/0x220 [brcmfmac]
+[ 186.678702] [<ffffffffc0c57fab>] brcmf_cfg80211_del_iface+0x21b/0x270 [brcmfmac]
+[ 186.678716] [<ffffffffc0b0539e>] nl80211_del_interface+0xfe/0x3a0 [cfg80211]
+[ 186.678718] [<ffffffff987ca335>] genl_family_rcv_msg+0x1b5/0x370
+[ 186.678720] [<ffffffff980e5d8d>] ? trace_hardirqs_on+0xd/0x10
+[ 186.678721] [<ffffffff987ca56d>] genl_rcv_msg+0x7d/0xb0
+[ 186.678722] [<ffffffff987ca4f0>] ? genl_family_rcv_msg+0x370/0x370
+[ 186.678724] [<ffffffff987c9a47>] netlink_rcv_skb+0x97/0xb0
+[ 186.678726] [<ffffffff987ca168>] genl_rcv+0x28/0x40
+[ 186.678727] [<ffffffff987c93c3>] netlink_unicast+0x1d3/0x2f0
+[ 186.678729] [<ffffffff987c933b>] ? netlink_unicast+0x14b/0x2f0
+[ 186.678731] [<ffffffff987c97cb>] netlink_sendmsg+0x2eb/0x3a0
+[ 186.678733] [<ffffffff9876dad8>] sock_sendmsg+0x38/0x50
+[ 186.678734] [<ffffffff9876e4df>] ___sys_sendmsg+0x27f/0x290
+[ 186.678737] [<ffffffff9828b935>] ? mntput_no_expire+0x5/0x3f0
+[ 186.678739] [<ffffffff9828b9be>] ? mntput_no_expire+0x8e/0x3f0
+[ 186.678741] [<ffffffff9828b935>] ? mntput_no_expire+0x5/0x3f0
+[ 186.678743] [<ffffffff9828bd44>] ? mntput+0x24/0x40
+[ 186.678744] [<ffffffff98267830>] ? __fput+0x190/0x200
+[ 186.678746] [<ffffffff9876f125>] __sys_sendmsg+0x45/0x80
+[ 186.678748] [<ffffffff9876f172>] SyS_sendmsg+0x12/0x20
+[ 186.678749] [<ffffffff988b5680>] entry_SYSCALL_64_fastpath+0x23/0xc1
+[ 186.678751] [<ffffffff980e2b8f>] ? trace_hardirqs_off_caller+0x1f/0xc0
+[ 186.678752] ---[ end trace e224d66c5d8408b5 ]---
+
+Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../broadcom/brcm80211/brcmfmac/cfg80211.c | 26 +++++++++++-----------
+ .../broadcom/brcm80211/brcmfmac/cfg80211.h | 2 +-
+ 2 files changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -5555,7 +5555,7 @@ static s32 brcmf_notify_vif_event(struct
+ ifevent->action, ifevent->flags, ifevent->ifidx,
+ ifevent->bsscfgidx);
+
+- mutex_lock(&event->vif_event_lock);
++ spin_lock(&event->vif_event_lock);
+ event->action = ifevent->action;
+ vif = event->vif;
+
+@@ -5563,7 +5563,7 @@ static s32 brcmf_notify_vif_event(struct
+ case BRCMF_E_IF_ADD:
+ /* waiting process may have timed out */
+ if (!cfg->vif_event.vif) {
+- mutex_unlock(&event->vif_event_lock);
++ spin_unlock(&event->vif_event_lock);
+ return -EBADF;
+ }
+
+@@ -5574,24 +5574,24 @@ static s32 brcmf_notify_vif_event(struct
+ ifp->ndev->ieee80211_ptr = &vif->wdev;
+ SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
+ }
+- mutex_unlock(&event->vif_event_lock);
++ spin_unlock(&event->vif_event_lock);
+ wake_up(&event->vif_wq);
+ return 0;
+
+ case BRCMF_E_IF_DEL:
+- mutex_unlock(&event->vif_event_lock);
++ spin_unlock(&event->vif_event_lock);
+ /* event may not be upon user request */
+ if (brcmf_cfg80211_vif_event_armed(cfg))
+ wake_up(&event->vif_wq);
+ return 0;
+
+ case BRCMF_E_IF_CHANGE:
+- mutex_unlock(&event->vif_event_lock);
++ spin_unlock(&event->vif_event_lock);
+ wake_up(&event->vif_wq);
+ return 0;
+
+ default:
+- mutex_unlock(&event->vif_event_lock);
++ spin_unlock(&event->vif_event_lock);
+ break;
+ }
+ return -EINVAL;
+@@ -5712,7 +5712,7 @@ static void wl_deinit_priv(struct brcmf_
+ static void init_vif_event(struct brcmf_cfg80211_vif_event *event)
+ {
+ init_waitqueue_head(&event->vif_wq);
+- mutex_init(&event->vif_event_lock);
++ spin_lock_init(&event->vif_event_lock);
+ }
+
+ static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
+@@ -6607,9 +6607,9 @@ static inline bool vif_event_equals(stru
+ {
+ u8 evt_action;
+
+- mutex_lock(&event->vif_event_lock);
++ spin_lock(&event->vif_event_lock);
+ evt_action = event->action;
+- mutex_unlock(&event->vif_event_lock);
++ spin_unlock(&event->vif_event_lock);
+ return evt_action == action;
+ }
+
+@@ -6618,10 +6618,10 @@ void brcmf_cfg80211_arm_vif_event(struct
+ {
+ struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
+
+- mutex_lock(&event->vif_event_lock);
++ spin_lock(&event->vif_event_lock);
+ event->vif = vif;
+ event->action = 0;
+- mutex_unlock(&event->vif_event_lock);
++ spin_unlock(&event->vif_event_lock);
+ }
+
+ bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg)
+@@ -6629,9 +6629,9 @@ bool brcmf_cfg80211_vif_event_armed(stru
+ struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
+ bool armed;
+
+- mutex_lock(&event->vif_event_lock);
++ spin_lock(&event->vif_event_lock);
+ armed = event->vif != NULL;
+- mutex_unlock(&event->vif_event_lock);
++ spin_unlock(&event->vif_event_lock);
+
+ return armed;
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -227,7 +227,7 @@ struct escan_info {
+ */
+ struct brcmf_cfg80211_vif_event {
+ wait_queue_head_t vif_wq;
+- struct mutex vif_event_lock;
++ spinlock_t vif_event_lock;
+ u8 action;
+ struct brcmf_cfg80211_vif *vif;
+ };
diff --git a/package/kernel/mac80211/patches/351-0033-brcmfmac-add-missing-header-dependencies.patch b/package/kernel/mac80211/patches/351-0033-brcmfmac-add-missing-header-dependencies.patch
new file mode 100644
index 0000000000..1a7947b39a
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0033-brcmfmac-add-missing-header-dependencies.patch
@@ -0,0 +1,29 @@
+From 8af92af3f2d55db143417a5d401696f4b642009a Mon Sep 17 00:00:00 2001
+From: Baoyou Xie <baoyou.xie@linaro.org>
+Date: Mon, 29 Aug 2016 20:39:35 +0800
+Subject: [PATCH] brcmfmac: add missing header dependencies
+
+We get 1 warning when building kernel with W=1:
+
+drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c:23:6: warning: no previous prototype for '__brcmf_err' [-Wmissing-prototypes]
+
+In fact, this function is declared in brcmfmac/debug.h, so this patch
+adds missing header dependencies.
+
+Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c
+@@ -19,6 +19,7 @@
+ #ifndef __CHECKER__
+ #define CREATE_TRACE_POINTS
+ #include "tracepoint.h"
++#include "debug.h"
+
+ void __brcmf_err(const char *func, const char *fmt, ...)
+ {
diff --git a/package/kernel/mac80211/patches/351-0034-brcmfmac-Add-USB-ID-for-Cisco-Linksys-AE1200.patch b/package/kernel/mac80211/patches/351-0034-brcmfmac-Add-USB-ID-for-Cisco-Linksys-AE1200.patch
new file mode 100644
index 0000000000..24cd92a8be
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0034-brcmfmac-Add-USB-ID-for-Cisco-Linksys-AE1200.patch
@@ -0,0 +1,51 @@
+From bccf3ffc8c6d8e0251a15541bb4d12b423c4f729 Mon Sep 17 00:00:00 2001
+From: Ismael Luceno <ismael@iodev.co.uk>
+Date: Mon, 22 Aug 2016 19:40:07 -0300
+Subject: [PATCH] brcmfmac: Add USB ID for Cisco Linksys AE1200
+
+The AE1200 comes with different revisions of the BCM43235 chipset,
+but all have the same USB ID. Only revision 3 can be supported.
+
+Signed-off-by: Ismael Luceno <ismael@iodev.co.uk>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 4 ++++
+ drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+@@ -1456,11 +1456,15 @@ static int brcmf_usb_reset_resume(struct
+ #define BRCMF_USB_DEVICE(dev_id) \
+ { USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) }
+
++#define LINKSYS_USB_DEVICE(dev_id) \
++ { USB_DEVICE(BRCM_USB_VENDOR_ID_LINKSYS, dev_id) }
++
+ static struct usb_device_id brcmf_usb_devid_table[] = {
+ BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID),
+ BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID),
+ BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID),
+ BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID),
++ LINKSYS_USB_DEVICE(BRCM_USB_43235_LINKSYS_DEVICE_ID),
+ { USB_DEVICE(BRCM_USB_VENDOR_ID_LG, BRCM_USB_43242_LG_DEVICE_ID) },
+ /* special entry for device with firmware loaded and running */
+ BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID),
+--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+@@ -22,6 +22,7 @@
+
+ #define BRCM_USB_VENDOR_ID_BROADCOM 0x0a5c
+ #define BRCM_USB_VENDOR_ID_LG 0x043e
++#define BRCM_USB_VENDOR_ID_LINKSYS 0x13b1
+ #define BRCM_PCIE_VENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
+
+ /* Chipcommon Core Chip IDs */
+@@ -56,6 +57,7 @@
+
+ /* USB Device IDs */
+ #define BRCM_USB_43143_DEVICE_ID 0xbd1e
++#define BRCM_USB_43235_LINKSYS_DEVICE_ID 0x0039
+ #define BRCM_USB_43236_DEVICE_ID 0xbd17
+ #define BRCM_USB_43242_DEVICE_ID 0xbd1f
+ #define BRCM_USB_43242_LG_DEVICE_ID 0x3101
diff --git a/package/kernel/mac80211/patches/351-0035-brcmfmac-fix-pmksa-bssid-usage.patch b/package/kernel/mac80211/patches/351-0035-brcmfmac-fix-pmksa-bssid-usage.patch
new file mode 100644
index 0000000000..b58a266a25
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0035-brcmfmac-fix-pmksa-bssid-usage.patch
@@ -0,0 +1,51 @@
+From 7703773ef1d85b40433902a8da20167331597e4a Mon Sep 17 00:00:00 2001
+From: Nicolas Iooss <nicolas.iooss_linux@m4x.org>
+Date: Tue, 23 Aug 2016 11:37:17 +0200
+Subject: [PATCH] brcmfmac: fix pmksa->bssid usage
+
+The struct cfg80211_pmksa defines its bssid field as:
+
+ const u8 *bssid;
+
+contrary to struct brcmf_pmksa, which uses:
+
+ u8 bssid[ETH_ALEN];
+
+Therefore in brcmf_cfg80211_del_pmksa(), &pmksa->bssid takes the address
+of this field (of type u8**), not the one of its content (which would be
+u8*). Remove the & operator to make brcmf_dbg("%pM") and memcmp()
+behave as expected.
+
+This bug have been found using a custom static checker (which checks the
+usage of %p... attributes at build time). It has been introduced in
+commit 6c404f34f2bd ("brcmfmac: Cleanup pmksa cache handling code"),
+which replaced pmksa->bssid by &pmksa->bssid while refactoring the code,
+without modifying struct cfg80211_pmksa definition.
+
+Replace &pmk[i].bssid with pmk[i].bssid too to make the code clearer,
+this change does not affect the semantic.
+
+Fixes: 6c404f34f2bd ("brcmfmac: Cleanup pmksa cache handling code")
+Cc: stable@vger.kernel.org
+Signed-off-by: Nicolas Iooss <nicolas.iooss_linux@m4x.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -3804,11 +3804,11 @@ brcmf_cfg80211_del_pmksa(struct wiphy *w
+ if (!check_vif_up(ifp->vif))
+ return -EIO;
+
+- brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", &pmksa->bssid);
++ brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", pmksa->bssid);
+
+ npmk = le32_to_cpu(cfg->pmk_list.npmk);
+ for (i = 0; i < npmk; i++)
+- if (!memcmp(&pmksa->bssid, &pmk[i].bssid, ETH_ALEN))
++ if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
+ break;
+
+ if ((npmk > 0) && (i < npmk)) {
diff --git a/package/kernel/mac80211/patches/351-0036-brcmfmac-avoid-potential-stack-overflow-in-brcmf_cfg.patch b/package/kernel/mac80211/patches/351-0036-brcmfmac-avoid-potential-stack-overflow-in-brcmf_cfg.patch
new file mode 100644
index 0000000000..760b6daf25
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0036-brcmfmac-avoid-potential-stack-overflow-in-brcmf_cfg.patch
@@ -0,0 +1,34 @@
+From ded89912156b1a47d940a0c954c43afbabd0c42c Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Mon, 5 Sep 2016 10:45:47 +0100
+Subject: [PATCH] brcmfmac: avoid potential stack overflow in
+ brcmf_cfg80211_start_ap()
+
+User-space can choose to omit NL80211_ATTR_SSID and only provide raw
+IE TLV data. When doing so it can provide SSID IE with length exceeding
+the allowed size. The driver further processes this IE copying it
+into a local variable without checking the length. Hence stack can be
+corrupted and used as exploit.
+
+Cc: stable@vger.kernel.org # v4.7
+Reported-by: Daxing Guo <freener.gdx@gmail.com>
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -4447,7 +4447,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+ (u8 *)&settings->beacon.head[ie_offset],
+ settings->beacon.head_len - ie_offset,
+ WLAN_EID_SSID);
+- if (!ssid_ie)
++ if (!ssid_ie || ssid_ie->len > IEEE80211_MAX_SSID_LEN)
+ return -EINVAL;
+
+ memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
diff --git a/package/kernel/mac80211/patches/351-0037-brcmfmac-add-support-for-bcm4339-chip-with-modalias-.patch b/package/kernel/mac80211/patches/351-0037-brcmfmac-add-support-for-bcm4339-chip-with-modalias-.patch
new file mode 100644
index 0000000000..1285b30960
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0037-brcmfmac-add-support-for-bcm4339-chip-with-modalias-.patch
@@ -0,0 +1,55 @@
+From 634faf3686900ccdee87b77e2c56df8b2159912b Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Mon, 5 Sep 2016 11:42:12 +0100
+Subject: [PATCH] brcmfmac: add support for bcm4339 chip with modalias
+ sdio:c00v02D0d4339
+
+The driver already supports the bcm4339 chipset but only for the variant
+that shares the same modalias as the bcm4335, ie. sdio:c00v02D0d4335.
+It turns out that there are also bcm4339 devices out there that have a
+more distiguishable modalias sdio:c00v02D0d4339.
+
+Reported-by: Steve deRosier <derosier@gmail.com>
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 1 +
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 3 ++-
+ include/linux/mmc/sdio_ids.h | 1 +
+ 3 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -1097,6 +1097,7 @@ static const struct sdio_device_id brcmf
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341),
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362),
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339),
++ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339),
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430),
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345),
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -3756,7 +3756,8 @@ static u32 brcmf_sdio_buscore_read32(voi
+ u32 val, rev;
+
+ val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
+- if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
++ if ((sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
++ sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
+ addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
+ rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
+ if (rev >= 2) {
+--- a/include/linux/mmc/sdio_ids.h
++++ b/include/linux/mmc/sdio_ids.h
+@@ -32,6 +32,7 @@
+ #define SDIO_DEVICE_ID_BROADCOM_43340 0xa94c
+ #define SDIO_DEVICE_ID_BROADCOM_43341 0xa94d
+ #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335
++#define SDIO_DEVICE_ID_BROADCOM_4339 0x4339
+ #define SDIO_DEVICE_ID_BROADCOM_43362 0xa962
+ #define SDIO_DEVICE_ID_BROADCOM_43430 0xa9a6
+ #define SDIO_DEVICE_ID_BROADCOM_4345 0x4345
diff --git a/package/kernel/mac80211/patches/351-0038-brcmfmac-sdio-shorten-retry-loop-in-brcmf_sdio_kso_c.patch b/package/kernel/mac80211/patches/351-0038-brcmfmac-sdio-shorten-retry-loop-in-brcmf_sdio_kso_c.patch
new file mode 100644
index 0000000000..1d5667ee6e
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0038-brcmfmac-sdio-shorten-retry-loop-in-brcmf_sdio_kso_c.patch
@@ -0,0 +1,56 @@
+From 5251b6be8bb5c5675bdf12347c7b83937a5c91e5 Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Mon, 5 Sep 2016 11:42:13 +0100
+Subject: [PATCH] brcmfmac: sdio: shorten retry loop in
+ brcmf_sdio_kso_control()
+
+In brcmf_sdio_kso_control() there is a retry loop as hardware may take
+time to settle. However, when the call to brcmf_sdiod_regrb() returns
+an error it is due to SDIO access failure and it makes no sense to wait
+for hardware to settle. This patch aborts the loop after a number of
+subsequent access errors.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+@@ -313,6 +313,7 @@ struct rte_console {
+
+ #define KSO_WAIT_US 50
+ #define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
++#define BRCMF_SDIO_MAX_ACCESS_ERRORS 5
+
+ /*
+ * Conversion of 802.1D priority to precedence level
+@@ -675,6 +676,7 @@ brcmf_sdio_kso_control(struct brcmf_sdio
+ {
+ u8 wr_val = 0, rd_val, cmp_val, bmask;
+ int err = 0;
++ int err_cnt = 0;
+ int try_cnt = 0;
+
+ brcmf_dbg(TRACE, "Enter: on=%d\n", on);
+@@ -710,9 +712,14 @@ brcmf_sdio_kso_control(struct brcmf_sdio
+ */
+ rd_val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ &err);
+- if (((rd_val & bmask) == cmp_val) && !err)
++ if (!err) {
++ if ((rd_val & bmask) == cmp_val)
++ break;
++ err_cnt = 0;
++ }
++ /* bail out upon subsequent access errors */
++ if (err && (err_cnt++ > BRCMF_SDIO_MAX_ACCESS_ERRORS))
+ break;
+-
+ udelay(KSO_WAIT_US);
+ brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ wr_val, &err);
diff --git a/package/kernel/mac80211/patches/351-0039-brcmfmac-ignore-11d-configuration-errors.patch b/package/kernel/mac80211/patches/351-0039-brcmfmac-ignore-11d-configuration-errors.patch
new file mode 100644
index 0000000000..1620e0022b
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0039-brcmfmac-ignore-11d-configuration-errors.patch
@@ -0,0 +1,84 @@
+From b3589dfe02123a0d0ea82076a9f8ef84a46852c0 Mon Sep 17 00:00:00 2001
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Mon, 19 Sep 2016 12:09:51 +0100
+Subject: [PATCH] brcmfmac: ignore 11d configuration errors
+
+802.11d is not always supported by firmware anymore. Currently the
+AP configuration of 11d will cause an abort if the ioctl set is
+failing. This behavior is not correct and the error should be
+ignored.
+
+Reviewed-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../broadcom/brcm80211/brcmfmac/cfg80211.c | 27 ++++++++++++----------
+ 1 file changed, 15 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -4422,6 +4422,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+ u16 chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);
+ bool mbss;
+ int is_11d;
++ bool supports_11d;
+
+ brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
+ settings->chandef.chan->hw_value,
+@@ -4434,11 +4435,16 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+ mbss = ifp->vif->mbss;
+
+ /* store current 11d setting */
+- brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_REGULATORY, &ifp->vif->is_11d);
+- country_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
+- settings->beacon.tail_len,
+- WLAN_EID_COUNTRY);
+- is_11d = country_ie ? 1 : 0;
++ if (brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_REGULATORY,
++ &ifp->vif->is_11d)) {
++ supports_11d = false;
++ } else {
++ country_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
++ settings->beacon.tail_len,
++ WLAN_EID_COUNTRY);
++ is_11d = country_ie ? 1 : 0;
++ supports_11d = true;
++ }
+
+ memset(&ssid_le, 0, sizeof(ssid_le));
+ if (settings->ssid == NULL || settings->ssid_len == 0) {
+@@ -4497,7 +4503,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+
+ /* Parameters shared by all radio interfaces */
+ if (!mbss) {
+- if (is_11d != ifp->vif->is_11d) {
++ if ((supports_11d) && (is_11d != ifp->vif->is_11d)) {
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
+ is_11d);
+ if (err < 0) {
+@@ -4539,7 +4545,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wi
+ brcmf_err("SET INFRA error %d\n", err);
+ goto exit;
+ }
+- } else if (WARN_ON(is_11d != ifp->vif->is_11d)) {
++ } else if (WARN_ON(supports_11d && (is_11d != ifp->vif->is_11d))) {
+ /* Multiple-BSS should use same 11d configuration */
+ err = -EINVAL;
+ goto exit;
+@@ -4673,11 +4679,8 @@ static int brcmf_cfg80211_stop_ap(struct
+ brcmf_err("setting INFRA mode failed %d\n", err);
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))
+ brcmf_fil_iovar_int_set(ifp, "mbss", 0);
+- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
+- ifp->vif->is_11d);
+- if (err < 0)
+- brcmf_err("restoring REGULATORY setting failed %d\n",
+- err);
++ brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
++ ifp->vif->is_11d);
+ /* Bring device back up so it can be used again */
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
+ if (err < 0)
diff --git a/package/kernel/mac80211/patches/351-0040-brcmfmac-rework-pointer-trickery-in-brcmf_proto_bcdc.patch b/package/kernel/mac80211/patches/351-0040-brcmfmac-rework-pointer-trickery-in-brcmf_proto_bcdc.patch
new file mode 100644
index 0000000000..9461164523
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0040-brcmfmac-rework-pointer-trickery-in-brcmf_proto_bcdc.patch
@@ -0,0 +1,32 @@
+From 704d1c6b56f4ee2ad6a5f012a72a278d17c1a223 Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Mon, 19 Sep 2016 12:09:52 +0100
+Subject: [PATCH] brcmfmac: rework pointer trickery in
+ brcmf_proto_bcdc_query_dcmd()
+
+The variable info is assigned to point to bcdc->msg[1], which is the
+same as pointing to bcdc->buf. As that is what we want to access
+make it clear by fixing the assignment. This also avoid out-of-bounds
+errors from static analyzers are bcdc->msg[1] is not in the structure
+definition.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
+@@ -194,7 +194,7 @@ retry:
+ }
+
+ /* Check info buffer */
+- info = (void *)&msg[1];
++ info = (void *)&bcdc->buf[0];
+
+ /* Copy info buffer */
+ if (buf) {
diff --git a/package/kernel/mac80211/patches/351-0041-brcmfmac-fix-memory-leak-in-brcmf_flowring_add_tdls_.patch b/package/kernel/mac80211/patches/351-0041-brcmfmac-fix-memory-leak-in-brcmf_flowring_add_tdls_.patch
new file mode 100644
index 0000000000..2ececdf197
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0041-brcmfmac-fix-memory-leak-in-brcmf_flowring_add_tdls_.patch
@@ -0,0 +1,39 @@
+From bc981641360183990de59da17f9f560f9150b801 Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Mon, 19 Sep 2016 12:09:53 +0100
+Subject: [PATCH] brcmfmac: fix memory leak in brcmf_flowring_add_tdls_peer()
+
+In the error paths in brcmf_flowring_add_tdls_peer() the allocated
+resource should be freed.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
+@@ -495,14 +495,18 @@ void brcmf_flowring_add_tdls_peer(struct
+ } else {
+ search = flow->tdls_entry;
+ if (memcmp(search->mac, peer, ETH_ALEN) == 0)
+- return;
++ goto free_entry;
+ while (search->next) {
+ search = search->next;
+ if (memcmp(search->mac, peer, ETH_ALEN) == 0)
+- return;
++ goto free_entry;
+ }
+ search->next = tdls_entry;
+ }
+
+ flow->tdls_active = true;
++ return;
++
++free_entry:
++ kfree(tdls_entry);
+ }
diff --git a/package/kernel/mac80211/patches/351-0042-brcmfmac-initialize-variable-in-brcmf_sdiod_regrl.patch b/package/kernel/mac80211/patches/351-0042-brcmfmac-initialize-variable-in-brcmf_sdiod_regrl.patch
new file mode 100644
index 0000000000..529cc8df02
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0042-brcmfmac-initialize-variable-in-brcmf_sdiod_regrl.patch
@@ -0,0 +1,28 @@
+From 26305d3d7298d1ddf8fd4ce95a382aa90534f0a3 Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Mon, 19 Sep 2016 12:09:54 +0100
+Subject: [PATCH] brcmfmac: initialize variable in brcmf_sdiod_regrl()
+
+In case of an error the variable returned is uninitialized. The caller
+will probably check the error code before using it, but better assure
+it is set to zero.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+@@ -416,7 +416,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d
+
+ u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
+ {
+- u32 data;
++ u32 data = 0;
+ int retval;
+
+ brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
diff --git a/package/kernel/mac80211/patches/351-0043-brcmfmac-remove-worker-from-.ndo_set_mac_address-cal.patch b/package/kernel/mac80211/patches/351-0043-brcmfmac-remove-worker-from-.ndo_set_mac_address-cal.patch
new file mode 100644
index 0000000000..67af30e4fd
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0043-brcmfmac-remove-worker-from-.ndo_set_mac_address-cal.patch
@@ -0,0 +1,107 @@
+From 8fa5fdec09cd379c9ecb8972f344f8f308e0ccf3 Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Mon, 19 Sep 2016 12:09:55 +0100
+Subject: [PATCH] brcmfmac: remove worker from .ndo_set_mac_address() callback
+
+As it turns out there is no need to use a worker for the callback
+because it is not called from atomic context.
+
+Reported-by: Dan Williams <dcbw@redhat.com>
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../wireless/broadcom/brcm80211/brcmfmac/core.c | 39 ++++++++--------------
+ .../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 --
+ 2 files changed, 13 insertions(+), 28 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -136,27 +136,6 @@ static void _brcmf_set_multicast_list(st
+ err);
+ }
+
+-static void
+-_brcmf_set_mac_address(struct work_struct *work)
+-{
+- struct brcmf_if *ifp;
+- s32 err;
+-
+- ifp = container_of(work, struct brcmf_if, setmacaddr_work);
+-
+- brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+-
+- err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
+- ETH_ALEN);
+- if (err < 0) {
+- brcmf_err("Setting cur_etheraddr failed, %d\n", err);
+- } else {
+- brcmf_dbg(TRACE, "MAC address updated to %pM\n",
+- ifp->mac_addr);
+- memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
+- }
+-}
+-
+ #if IS_ENABLED(CONFIG_IPV6)
+ static void _brcmf_update_ndtable(struct work_struct *work)
+ {
+@@ -190,10 +169,20 @@ static int brcmf_netdev_set_mac_address(
+ {
+ struct brcmf_if *ifp = netdev_priv(ndev);
+ struct sockaddr *sa = (struct sockaddr *)addr;
++ int err;
+
+- memcpy(&ifp->mac_addr, sa->sa_data, ETH_ALEN);
+- schedule_work(&ifp->setmacaddr_work);
+- return 0;
++ brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
++
++ err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", sa->sa_data,
++ ETH_ALEN);
++ if (err < 0) {
++ brcmf_err("Setting cur_etheraddr failed, %d\n", err);
++ } else {
++ brcmf_dbg(TRACE, "updated to %pM\n", sa->sa_data);
++ memcpy(ifp->mac_addr, sa->sa_data, ETH_ALEN);
++ memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
++ }
++ return err;
+ }
+
+ static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
+@@ -525,7 +514,6 @@ int brcmf_net_attach(struct brcmf_if *if
+ /* set the mac address */
+ memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
+
+- INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
+ INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
+ INIT_WORK(&ifp->ndoffload_work, _brcmf_update_ndtable);
+
+@@ -730,7 +718,6 @@ static void brcmf_del_if(struct brcmf_pu
+ }
+
+ if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+- cancel_work_sync(&ifp->setmacaddr_work);
+ cancel_work_sync(&ifp->multicast_work);
+ cancel_work_sync(&ifp->ndoffload_work);
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -176,7 +176,6 @@ enum brcmf_netif_stop_reason {
+ * @vif: points to cfg80211 specific interface information.
+ * @ndev: associated network device.
+ * @stats: interface specific network statistics.
+- * @setmacaddr_work: worker object for setting mac address.
+ * @multicast_work: worker object for multicast provisioning.
+ * @ndoffload_work: worker object for neighbor discovery offload configuration.
+ * @fws_desc: interface specific firmware-signalling descriptor.
+@@ -193,7 +192,6 @@ struct brcmf_if {
+ struct brcmf_cfg80211_vif *vif;
+ struct net_device *ndev;
+ struct net_device_stats stats;
+- struct work_struct setmacaddr_work;
+ struct work_struct multicast_work;
+ struct work_struct ndoffload_work;
+ struct brcmf_fws_mac_descriptor *fws_desc;
diff --git a/package/kernel/mac80211/patches/351-0044-brcmfmac-remove-unnecessary-null-pointer-check.patch b/package/kernel/mac80211/patches/351-0044-brcmfmac-remove-unnecessary-null-pointer-check.patch
new file mode 100644
index 0000000000..5a08479329
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0044-brcmfmac-remove-unnecessary-null-pointer-check.patch
@@ -0,0 +1,31 @@
+From 835680b82f029818c813324aed3073cdcf63241f Mon Sep 17 00:00:00 2001
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Mon, 19 Sep 2016 12:09:56 +0100
+Subject: [PATCH] brcmfmac: remove unnecessary null pointer check
+
+in the function brcmf_bus_start() in the exception handling a
+check is made to dermine whether ifp is null, though this is not
+possible. Removing the unnessary check.
+
+Reviewed-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1048,8 +1048,7 @@ fail:
+ brcmf_fws_del_interface(ifp);
+ brcmf_fws_deinit(drvr);
+ }
+- if (ifp)
+- brcmf_net_detach(ifp->ndev, false);
++ brcmf_net_detach(ifp->ndev, false);
+ if (p2p_ifp)
+ brcmf_net_detach(p2p_ifp->ndev, false);
+ drvr->iflist[0] = NULL;
diff --git a/package/kernel/mac80211/patches/351-0045-brcmfmac-fix-clearing-entry-IPv6-address.patch b/package/kernel/mac80211/patches/351-0045-brcmfmac-fix-clearing-entry-IPv6-address.patch
new file mode 100644
index 0000000000..0b3a23edc0
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0045-brcmfmac-fix-clearing-entry-IPv6-address.patch
@@ -0,0 +1,37 @@
+From 2b7425f3629b38c438f890c20c5faeca64b144ff Mon Sep 17 00:00:00 2001
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Mon, 19 Sep 2016 12:09:57 +0100
+Subject: [PATCH] brcmfmac: fix clearing entry IPv6 address
+
+When IPv6 address is to be cleared there is a possible out of
+bound access. But also the clearing of the last entry and the
+adjustment of total number of stored IPv6 addresses is not
+updated. This patch fixes that bug. Bug was found using coverity.
+
+Reviewed-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -873,9 +873,12 @@ static int brcmf_inet6addr_changed(struc
+ }
+ break;
+ case NETDEV_DOWN:
+- if (i < NDOL_MAX_ENTRIES)
+- for (; i < ifp->ipv6addr_idx; i++)
++ if (i < NDOL_MAX_ENTRIES) {
++ for (; i < ifp->ipv6addr_idx - 1; i++)
+ table[i] = table[i + 1];
++ memset(&table[i], 0, sizeof(table[i]));
++ ifp->ipv6addr_idx--;
++ }
+ break;
+ default:
+ break;
diff --git a/package/kernel/mac80211/patches/351-0046-brcmfmac-fix-out-of-bound-access-on-clearing-wowl-wa.patch b/package/kernel/mac80211/patches/351-0046-brcmfmac-fix-out-of-bound-access-on-clearing-wowl-wa.patch
new file mode 100644
index 0000000000..a47cb3266f
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0046-brcmfmac-fix-out-of-bound-access-on-clearing-wowl-wa.patch
@@ -0,0 +1,44 @@
+From a7ed7828ecda0c2b5e0d7f55dedd4230afd4b583 Mon Sep 17 00:00:00 2001
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Mon, 19 Sep 2016 12:09:58 +0100
+Subject: [PATCH] brcmfmac: fix out of bound access on clearing wowl wake
+ indicator
+
+Clearing the wowl wakeindicator happens with a rather odd
+construction where the string "clear" is used to set the iovar
+wowl_wakeind. This was implemented incorrectly as it caused an
+out of bound access. Use an intermediate variable of correct
+length and copy string in that. Problem was found using coverity.
+
+Reviewed-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -3623,6 +3623,7 @@ static void brcmf_configure_wowl(struct
+ struct cfg80211_wowlan *wowl)
+ {
+ u32 wowl_config;
++ struct brcmf_wowl_wakeind_le wowl_wakeind;
+ u32 i;
+
+ brcmf_dbg(TRACE, "Suspend, wowl config.\n");
+@@ -3664,8 +3665,9 @@ static void brcmf_configure_wowl(struct
+ if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
+ wowl_config |= BRCMF_WOWL_UNASSOC;
+
+- brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear",
+- sizeof(struct brcmf_wowl_wakeind_le));
++ memcpy(&wowl_wakeind, "clear", 6);
++ brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", &wowl_wakeind,
++ sizeof(wowl_wakeind));
+ brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
+ brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
+ brcmf_bus_wowl_config(cfg->pub->bus_if, true);
diff --git a/package/kernel/mac80211/patches/351-0047-brcmfmac-simplify-mapping-of-auth-type.patch b/package/kernel/mac80211/patches/351-0047-brcmfmac-simplify-mapping-of-auth-type.patch
new file mode 100644
index 0000000000..a652ae60b8
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0047-brcmfmac-simplify-mapping-of-auth-type.patch
@@ -0,0 +1,39 @@
+From 92c313604711a0976def79dabb9e8da3cc2cc780 Mon Sep 17 00:00:00 2001
+From: Hante Meuleman <hante.meuleman@broadcom.com>
+Date: Mon, 19 Sep 2016 12:09:59 +0100
+Subject: [PATCH] brcmfmac: simplify mapping of auth type
+
+The 802.11 standard only has four valid auth type configurations of which
+our firmware only supports two, ie. Open System and Shared Key. Simplify
+the mapping falling back to automatic for other types specified by
+user-space.
+
+Reviewed-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Signed-off-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -1577,15 +1577,9 @@ static s32 brcmf_set_auth_type(struct ne
+ val = 1;
+ brcmf_dbg(CONN, "shared key\n");
+ break;
+- case NL80211_AUTHTYPE_AUTOMATIC:
+- val = 2;
+- brcmf_dbg(CONN, "automatic\n");
+- break;
+- case NL80211_AUTHTYPE_NETWORK_EAP:
+- brcmf_dbg(CONN, "network eap\n");
+ default:
+ val = 2;
+- brcmf_err("invalid auth type (%d)\n", sme->auth_type);
++ brcmf_dbg(CONN, "automatic, auth type (%d)\n", sme->auth_type);
+ break;
+ }
+
diff --git a/package/kernel/mac80211/patches/351-0048-brcmfmac-fix-memory-leak-in-brcmf_fill_bss_param.patch b/package/kernel/mac80211/patches/351-0048-brcmfmac-fix-memory-leak-in-brcmf_fill_bss_param.patch
new file mode 100644
index 0000000000..a6fae37803
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0048-brcmfmac-fix-memory-leak-in-brcmf_fill_bss_param.patch
@@ -0,0 +1,41 @@
+From 23e9c128adb2038c27a424a5f91136e7fa3e0dc6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Wed, 21 Sep 2016 08:23:24 +0200
+Subject: [PATCH] brcmfmac: fix memory leak in brcmf_fill_bss_param
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This function is called from get_station callback which means that every
+time user space was getting/dumping station(s) we were leaking 2 KiB.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Fixes: 1f0dc59a6de ("brcmfmac: rework .get_station() callback")
+Cc: stable@vger.kernel.org # 4.2+
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -2463,7 +2463,7 @@ static void brcmf_fill_bss_param(struct
+ WL_BSS_INFO_MAX);
+ if (err) {
+ brcmf_err("Failed to get bss info (%d)\n", err);
+- return;
++ goto out_kfree;
+ }
+ si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
+ si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
+@@ -2475,6 +2475,9 @@ static void brcmf_fill_bss_param(struct
+ si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
+ if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+ si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
++
++out_kfree:
++ kfree(buf);
+ }
+
+ static s32
diff --git a/package/kernel/mac80211/patches/351-0049-brcmfmac-drop-unused-fields-from-struct-brcmf_pub.patch b/package/kernel/mac80211/patches/351-0049-brcmfmac-drop-unused-fields-from-struct-brcmf_pub.patch
new file mode 100644
index 0000000000..47af73ad29
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0049-brcmfmac-drop-unused-fields-from-struct-brcmf_pub.patch
@@ -0,0 +1,60 @@
+From 2df86ad959c9d1cdbeb2f23a0801857731156692 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 23 Sep 2016 15:27:46 +0200
+Subject: [PATCH] brcmfmac: drop unused fields from struct brcmf_pub
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+They seem to be there from the first day. We calculate these values but
+never use them.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 3 ---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h | 4 ----
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c | 2 --
+ 3 files changed, 9 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -508,9 +508,6 @@ int brcmf_net_attach(struct brcmf_if *if
+ ndev->hard_header_len += drvr->hdrlen;
+ ndev->ethtool_ops = &brcmf_ethtool_ops;
+
+- drvr->rxsz = ndev->mtu + ndev->hard_header_len +
+- drvr->hdrlen;
+-
+ /* set the mac address */
+ memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+@@ -112,15 +112,11 @@ struct brcmf_pub {
+
+ /* Internal brcmf items */
+ uint hdrlen; /* Total BRCMF header length (proto + bus) */
+- uint rxsz; /* Rx buffer size bus module should use */
+
+ /* Dongle media info */
+ char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN];
+ u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
+
+- /* Multicast data packets sent to dongle */
+- unsigned long tx_multicast;
+-
+ struct mac_address addresses[BRCMF_MAX_IFS];
+
+ struct brcmf_if *iflist[BRCMF_MAX_IFS];
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+@@ -2104,8 +2104,6 @@ int brcmf_fws_process_skb(struct brcmf_i
+ if (!skb->priority)
+ skb->priority = cfg80211_classify8021d(skb, NULL);
+
+- drvr->tx_multicast += !!multicast;
+-
+ if (fws->avoid_queueing) {
+ rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
+ if (rc < 0)
diff --git a/package/kernel/mac80211/patches/351-0050-brcmfmac-replace-WARNING-on-timeout-with-a-simple-er.patch b/package/kernel/mac80211/patches/351-0050-brcmfmac-replace-WARNING-on-timeout-with-a-simple-er.patch
new file mode 100644
index 0000000000..ca4863a195
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0050-brcmfmac-replace-WARNING-on-timeout-with-a-simple-er.patch
@@ -0,0 +1,38 @@
+From 2f0e56fa37cce60a5ac5d451bcadec51cd711436 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Tue, 27 Sep 2016 12:12:24 +0200
+Subject: [PATCH] brcmfmac: replace WARNING on timeout with a simple error
+ message
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Even with timeout increased to 950 ms we get WARNINGs from time to time.
+It mostly happens on A-MPDU stalls (e.g. when station goes out of
+range). It may take up to 5-10 secods for the firmware to recover and
+for that time it doesn't process packets.
+
+It's still useful to have a message on time out as it may indicate some
+firmware problem and incorrect key update. Raising a WARNING however
+wasn't really that necessary, it doesn't point to any driver bug anymore
+and backtrace wasn't much useful.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1155,7 +1155,8 @@ int brcmf_netdev_wait_pend8021x(struct b
+ !brcmf_get_pend_8021x_cnt(ifp),
+ MAX_WAIT_FOR_8021X_TX);
+
+- WARN_ON(!err);
++ if (!err)
++ brcmf_err("Timed out waiting for no pending 802.1x packets\n");
+
+ return !err;
+ }
diff --git a/package/kernel/mac80211/patches/351-0051-brcmfmac-use-correct-skb-freeing-helper-when-deletin.patch b/package/kernel/mac80211/patches/351-0051-brcmfmac-use-correct-skb-freeing-helper-when-deletin.patch
new file mode 100644
index 0000000000..697635941b
--- /dev/null
+++ b/package/kernel/mac80211/patches/351-0051-brcmfmac-use-correct-skb-freeing-helper-when-deletin.patch
@@ -0,0 +1,58 @@
+From 7f00ee2bbc630900ba16fc2690473f3e2db0e264 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Tue, 27 Sep 2016 14:11:04 +0200
+Subject: [PATCH] brcmfmac: use correct skb freeing helper when deleting
+ flowring
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Flowrings contain skbs waiting for transmission that were passed to us
+by netif. It means we checked every one of them looking for 802.1x
+Ethernet type. When deleting flowring we have to use freeing function
+that will check for 802.1x type as well.
+
+Freeing skbs without a proper check was leading to counter not being
+properly decreased. This was triggering a WARNING every time
+brcmf_netdev_wait_pend8021x was called.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Acked-by: Arend van Spriel <arend@broadcom.com>
+Cc: stable@vger.kernel.org # 4.5+
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
+@@ -234,13 +234,20 @@ static void brcmf_flowring_block(struct
+
+ void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid)
+ {
++ struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+ struct brcmf_flowring_ring *ring;
++ struct brcmf_if *ifp;
+ u16 hash_idx;
++ u8 ifidx;
+ struct sk_buff *skb;
+
+ ring = flow->rings[flowid];
+ if (!ring)
+ return;
++
++ ifidx = brcmf_flowring_ifidx_get(flow, flowid);
++ ifp = brcmf_get_ifp(bus_if->drvr, ifidx);
++
+ brcmf_flowring_block(flow, flowid, false);
+ hash_idx = ring->hash_id;
+ flow->hash[hash_idx].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
+@@ -249,7 +256,7 @@ void brcmf_flowring_delete(struct brcmf_
+
+ skb = skb_dequeue(&ring->skblist);
+ while (skb) {
+- brcmu_pkt_buf_free_skb(skb);
++ brcmf_txfinalize(ifp, skb, false);
+ skb = skb_dequeue(&ring->skblist);
+ }
+
diff --git a/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch b/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch
new file mode 100644
index 0000000000..e2653542de
--- /dev/null
+++ b/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch
@@ -0,0 +1,26 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Subject: [PATCH] brcmfmac: add missing eth_type_trans call
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There are 2 protocols supported by brcmfmac and msgbuf one was missing a
+proper skb setup before passing it to the netif. This was triggering
+"NULL pointer dereference".
+
+Fixes: 9c349892ccc9 ("brcmfmac: revise handling events in receive path")
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+@@ -1157,6 +1157,9 @@ brcmf_msgbuf_process_rx_complete(struct
+ brcmu_pkt_buf_free_skb(skb);
+ return;
+ }
++
++ skb->protocol = eth_type_trans(skb, ifp->ndev);
++
+ brcmf_netif_rx(ifp, skb);
+ }
+
diff --git a/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch
index 77c12741ef..f7f44f513f 100644
--- a/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch
+++ b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch
@@ -13,8 +13,8 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1308,6 +1308,7 @@ static int __init brcmfmac_module_init(v
- #endif
+@@ -1200,6 +1200,7 @@ int __init brcmf_core_init(void)
+ {
if (!schedule_work(&brcmf_driver_work))
return -EBUSY;
+ flush_work(&brcmf_driver_work);
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 6e309e9fa1..1e440c02f3 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,7 +10,7 @@ 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
-@@ -630,9 +630,37 @@ static struct wireless_dev *brcmf_cfg802
+@@ -651,9 +651,37 @@ static struct wireless_dev *brcmf_cfg802
u32 *flags,
struct vif_params *params)
{
diff --git a/package/kernel/mwlwifi/Makefile b/package/kernel/mwlwifi/Makefile
index 091928df71..f59943d296 100644
--- a/package/kernel/mwlwifi/Makefile
+++ b/package/kernel/mwlwifi/Makefile
@@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mwlwifi
-PKG_VERSION:=10.3.0.16-20160105
+PKG_VERSION:=10.3.0.18-20160804
PKG_RELEASE=1
PKG_LICENSE:=ISC
@@ -17,7 +17,7 @@ PKG_LICENSE_FILES:=
PKG_SOURCE_URL:=https://github.com/kaloz/mwlwifi
PKG_SOURCE_PROTO:=git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
-PKG_SOURCE_VERSION:=99d3879cc72f2a25d44fb4bee96fd84eca028b04
+PKG_SOURCE_VERSION:=d48847cc83954930fdcd98818bbf33e75707b8e1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz
PKG_MAINTAINER:=Imre Kaloz <kaloz@openwrt.org>
diff --git a/package/kernel/mwlwifi/patches/100-drop_old_api.patch b/package/kernel/mwlwifi/patches/100-drop_old_api.patch
deleted file mode 100644
index d2e149e9a2..0000000000
--- a/package/kernel/mwlwifi/patches/100-drop_old_api.patch
+++ /dev/null
@@ -1,92 +0,0 @@
---- a/main.c
-+++ b/main.c
-@@ -418,11 +418,7 @@ static void mwl_set_ht_caps(struct mwl_p
- band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
- band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
-- hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
--#else
- ieee80211_hw_set(hw, AMPDU_AGGREGATION);
--#endif
- band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
- band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
-
-@@ -524,29 +520,16 @@ static int mwl_wl_init(struct mwl_priv *
- hw->queues = SYSADPT_TX_WMM_QUEUES;
-
- /* Set rssi values to dBm */
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
-- hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL;
--#else
- ieee80211_hw_set(hw, SIGNAL_DBM);
- ieee80211_hw_set(hw, HAS_RATE_CONTROL);
--#endif
-
- /* Ask mac80211 not to trigger PS mode
- * based on PM bit of incoming frames.
- */
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
-- hw->flags |= IEEE80211_HW_AP_LINK_PS;
--#else
- ieee80211_hw_set(hw, AP_LINK_PS);
--#endif
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
-- hw->flags |= IEEE80211_HW_SUPPORTS_PER_STA_GTK |
-- IEEE80211_HW_MFP_CAPABLE;
--#else
- ieee80211_hw_set(hw, SUPPORTS_PER_STA_GTK);
- ieee80211_hw_set(hw, MFP_CAPABLE);
--#endif
-
- hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
-
---- a/dev.h
-+++ b/dev.h
-@@ -484,10 +484,6 @@ static inline struct mwl_sta *mwl_dev_ge
- return (struct mwl_sta *)&sta->drv_priv;
- }
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
--#define ether_addr_copy(dst, src) memcpy(dst, src, ETH_ALEN)
--#endif
--
- /* Defined in mac80211.c. */
- extern const struct ieee80211_ops mwl_mac80211_ops;
-
---- a/mac80211.c
-+++ b/mac80211.c
-@@ -572,19 +572,11 @@ static int mwl_mac80211_get_survey(struc
- return 0;
- }
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
--static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
-- struct ieee80211_vif *vif,
-- enum ieee80211_ampdu_mlme_action action,
-- struct ieee80211_sta *sta,
-- u16 tid, u16 *ssn, u8 buf_size)
--#else
- static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum ieee80211_ampdu_mlme_action action,
- struct ieee80211_sta *sta,
- u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
--#endif
- {
- int rc = 0;
- struct mwl_priv *priv = hw->priv;
---- a/rx.c
-+++ b/rx.c
-@@ -232,10 +232,8 @@ static inline void mwl_rx_prepare_status
- status->flag |= RX_FLAG_VHT;
- if (bw == RX_RATE_INFO_HT40)
- status->flag |= RX_FLAG_40MHZ;
--#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 18, 0)
- if (bw == RX_RATE_INFO_HT80)
- status->vht_flag |= RX_VHT_FLAG_80MHZ;
--#endif
- if (gi == RX_RATE_INFO_SHORT_INTERVAL)
- status->flag |= RX_FLAG_SHORT_GI;
- status->vht_nss = (nss + 1);
diff --git a/package/kernel/mwlwifi/patches/110-api_sync.patch b/package/kernel/mwlwifi/patches/110-api_sync.patch
deleted file mode 100644
index ed3e06a1c1..0000000000
--- a/package/kernel/mwlwifi/patches/110-api_sync.patch
+++ /dev/null
@@ -1,19 +0,0 @@
---- a/mac80211.c
-+++ b/mac80211.c
-@@ -597,10 +597,13 @@ static int mwl_mac80211_get_survey(struc
-
- static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
-- enum ieee80211_ampdu_mlme_action action,
-- struct ieee80211_sta *sta,
-- u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
-+ struct ieee80211_ampdu_params *params)
- {
-+ enum ieee80211_ampdu_mlme_action action = params->action;
-+ struct ieee80211_sta *sta = params->sta;
-+ u16 tid = params->tid;
-+ u16 *ssn = &params->ssn;
-+ u8 buf_size = params->buf_size;
- int rc = 0;
- struct mwl_priv *priv = hw->priv;
- struct mwl_ampdu_stream *stream;
diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile
index 3d13fe0a8b..ea68f167fb 100644
--- a/package/libs/openssl/Makefile
+++ b/package/libs/openssl/Makefile
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=openssl
PKG_BASE:=1.0.2
-PKG_BUGFIX:=h
+PKG_BUGFIX:=j
PKG_VERSION:=$(PKG_BASE)$(PKG_BUGFIX)
PKG_RELEASE:=1
PKG_USE_MIPS16:=0
@@ -21,7 +21,7 @@ PKG_SOURCE_URL:=http://www.openssl.org/source/ \
http://www.openssl.org/source/old/$(PKG_BASE)/ \
ftp://ftp.funet.fi/pub/crypt/mirrors/ftp.openssl.org/source \
ftp://ftp.sunet.se/pub/security/tools/net/openssl/source/
-PKG_MD5SUM:=9392e65072ce4b614c1392eefc1f23d0
+PKG_MD5SUM:=96322138f0b69e61b7212bc53d5e912b
PKG_LICENSE:=OpenSSL
PKG_LICENSE_FILES:=LICENSE
diff --git a/package/system/rpcd/Makefile b/package/system/rpcd/Makefile
index 86bd8c5686..80f131d0df 100644
--- a/package/system/rpcd/Makefile
+++ b/package/system/rpcd/Makefile
@@ -8,13 +8,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=rpcd
-PKG_VERSION:=2016-04-13
+PKG_VERSION:=2016-06-30
PKG_RELEASE=$(PKG_SOURCE_VERSION)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(OPENWRT_GIT)/project/rpcd.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
-PKG_SOURCE_VERSION:=73aea9b8b621a1ce034bc6ee00c9d058a40c8a3d
+PKG_SOURCE_VERSION:=23417e94d25570e6d62542bac46edd51e8e0243a
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org>
diff --git a/target/linux/ar71xx/patches-3.18/003-MIPS-ath79-make-bootconsole-wait-for-both-THRE-and-T.patch b/target/linux/ar71xx/patches-3.18/003-MIPS-ath79-make-bootconsole-wait-for-both-THRE-and-T.patch
deleted file mode 100644
index 2eba263732..0000000000
--- a/target/linux/ar71xx/patches-3.18/003-MIPS-ath79-make-bootconsole-wait-for-both-THRE-and-T.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From f1ba020af5076172c9d29006a747ccf40027fedc Mon Sep 17 00:00:00 2001
-Message-Id: <f1ba020af5076172c9d29006a747ccf40027fedc.1458840219.git.mschiffer@universe-factory.net>
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Thu, 24 Mar 2016 15:34:05 +0100
-Subject: [PATCH] MIPS: ath79: make bootconsole wait for both THRE and TEMT
-
-This makes the ath79 bootconsole behave the same way as the generic 8250
-bootconsole.
-
-Also waiting for TEMT (transmit buffer is empty) instead of just THRE
-(transmit buffer is not full) ensures that all characters have been
-transmitted before the real serial driver starts reconfiguring the serial
-controller (which would sometimes result in garbage being transmitted.)
-This change does not cause a visible performance loss.
-
-In addition, this seems to fix a hang observed in certain configurations on
-many AR7xxx/AR9xxx SoCs during autoconfig of the real serial driver.
-
-A more complete follow-up patch will disable 8250 autoconfig for ath79
-altogether (the serial controller is detected as a 16550A, which is not
-fully compatible with the ath79 serial, and the autoconfig may lead to
-undefined behavior on ath79.)
-
-Cc: <stable@vger.kernel.org>
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
----
- arch/mips/ath79/early_printk.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/arch/mips/ath79/early_printk.c
-+++ b/arch/mips/ath79/early_printk.c
-@@ -31,13 +31,15 @@ static inline void prom_putchar_wait(voi
- } while (1);
- }
-
-+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-+
- static void prom_putchar_ar71xx(unsigned char ch)
- {
- void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
-
-- prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
-+ prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
- __raw_writel(ch, base + UART_TX * 4);
-- prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
-+ prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
- }
-
- static void prom_putchar_ar933x(unsigned char ch)
diff --git a/target/linux/ar71xx/patches-3.18/718-MIPS-ath79-add-EPG5000-support.patch b/target/linux/ar71xx/patches-3.18/718-MIPS-ath79-add-EPG5000-support.patch
index a47e24d61b..d083c7bc3c 100644
--- a/target/linux/ar71xx/patches-3.18/718-MIPS-ath79-add-EPG5000-support.patch
+++ b/target/linux/ar71xx/patches-3.18/718-MIPS-ath79-add-EPG5000-support.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -196,6 +196,17 @@ config ATH79_MACH_F9K1115V2
+@@ -205,6 +205,17 @@ config ATH79_MACH_F9K1115V2
select ATH79_DEV_USB
select ATH79_DEV_WMAC
@@ -20,7 +20,7 @@
select SOC_QCA955X
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
-@@ -72,6 +72,7 @@ obj-$(CONFIG_ATH79_MACH_EAP300V2) += mac
+@@ -73,6 +73,7 @@ obj-$(CONFIG_ATH79_MACH_EAP300V2) += mac
obj-$(CONFIG_ATH79_MACH_EAP7660D) += mach-eap7660d.o
obj-$(CONFIG_ATH79_MACH_EL_M150) += mach-el-m150.o
obj-$(CONFIG_ATH79_MACH_EL_MINI) += mach-el-mini.o
@@ -30,7 +30,7 @@
obj-$(CONFIG_ATH79_MACH_GL_INET) += mach-gl-inet.o
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -62,6 +62,7 @@ enum ath79_mach_type {
+@@ -63,6 +63,7 @@ enum ath79_mach_type {
ATH79_MACH_EL_M150, /* EasyLink EL-M150 */
ATH79_MACH_EL_MINI, /* EasyLink EL-MINI */
ATH79_MACH_ESR1750, /* EnGenius ESR1750 */
diff --git a/target/linux/ar71xx/patches-3.18/736-MIPS-ath79-add-MC-MAC1200R-support.patch b/target/linux/ar71xx/patches-3.18/736-MIPS-ath79-add-MC-MAC1200R-support.patch
index cef612b300..b4d3ec100c 100644
--- a/target/linux/ar71xx/patches-3.18/736-MIPS-ath79-add-MC-MAC1200R-support.patch
+++ b/target/linux/ar71xx/patches-3.18/736-MIPS-ath79-add-MC-MAC1200R-support.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -590,6 +590,16 @@ config ATH79_MACH_R6100
+@@ -599,6 +599,16 @@ config ATH79_MACH_R6100
select ATH79_DEV_USB
select ATH79_DEV_WMAC
@@ -19,7 +19,7 @@
select SOC_AR71XX
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
-@@ -81,6 +81,7 @@ obj-$(CONFIG_ATH79_MACH_HIWIFI_HC6361) +
+@@ -82,6 +82,7 @@ obj-$(CONFIG_ATH79_MACH_HIWIFI_HC6361) +
obj-$(CONFIG_ATH79_MACH_JA76PF) += mach-ja76pf.o
obj-$(CONFIG_ATH79_MACH_JWAP003) += mach-jwap003.o
obj-$(CONFIG_ATH79_MACH_HORNET_UB) += mach-hornet-ub.o
@@ -29,7 +29,7 @@
obj-$(CONFIG_ATH79_MACH_MYNET_N600) += mach-mynet-n600.o
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -121,6 +121,7 @@ enum ath79_mach_type {
+@@ -122,6 +122,7 @@ enum ath79_mach_type {
ATH79_MACH_TEW_673GRU, /* TRENDnet TEW-673GRU */
ATH79_MACH_TEW_712BR, /* TRENDnet TEW-712BR */
ATH79_MACH_TEW_732BR, /* TRENDnet TEW-732BR */
diff --git a/target/linux/ar71xx/patches-3.18/737-MIPS-ath79-add-om5p-an-support.patch b/target/linux/ar71xx/patches-3.18/737-MIPS-ath79-add-om5p-an-support.patch
index 3fbfba7024..137a09ab50 100644
--- a/target/linux/ar71xx/patches-3.18/737-MIPS-ath79-add-om5p-an-support.patch
+++ b/target/linux/ar71xx/patches-3.18/737-MIPS-ath79-add-om5p-an-support.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -87,6 +87,7 @@ enum ath79_mach_type {
+@@ -88,6 +88,7 @@ enum ath79_mach_type {
ATH79_MACH_OM2P_LC, /* OpenMesh OM2P-LC */
ATH79_MACH_OM2Pv2, /* OpenMesh OM2Pv2 */
ATH79_MACH_OM2P, /* OpenMesh OM2P */
@@ -10,7 +10,7 @@
ATH79_MACH_PB42, /* Atheros PB42 */
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -743,6 +743,7 @@ config ATH79_MACH_OM2P
+@@ -752,6 +752,7 @@ config ATH79_MACH_OM2P
config ATH79_MACH_OM5P
bool "OpenMesh OM5P board support"
select SOC_AR934X
diff --git a/target/linux/ar71xx/patches-3.18/738-MIPS-ath79-add-meraki-mr12-mr16-support.patch b/target/linux/ar71xx/patches-3.18/738-MIPS-ath79-add-meraki-mr12-mr16-support.patch
index ceee0aa05c..84ae4003af 100644
--- a/target/linux/ar71xx/patches-3.18/738-MIPS-ath79-add-meraki-mr12-mr16-support.patch
+++ b/target/linux/ar71xx/patches-3.18/738-MIPS-ath79-add-meraki-mr12-mr16-support.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -760,6 +760,26 @@ config ATH79_MACH_ONION_OMEGA
+@@ -769,6 +769,26 @@ config ATH79_MACH_ONION_OMEGA
select ATH79_DEV_USB
select ATH79_DEV_WMAC
@@ -29,7 +29,7 @@
select SOC_AR934X
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
-@@ -82,6 +82,8 @@ obj-$(CONFIG_ATH79_MACH_JA76PF) += mach
+@@ -83,6 +83,8 @@ obj-$(CONFIG_ATH79_MACH_JA76PF) += mach
obj-$(CONFIG_ATH79_MACH_JWAP003) += mach-jwap003.o
obj-$(CONFIG_ATH79_MACH_HORNET_UB) += mach-hornet-ub.o
obj-$(CONFIG_ATH79_MACH_MC_MAC1200R) += mach-mc-mac1200r.o
@@ -40,7 +40,7 @@
obj-$(CONFIG_ATH79_MACH_MYNET_N600) += mach-mynet-n600.o
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -71,6 +71,8 @@ enum ath79_mach_type {
+@@ -72,6 +72,8 @@ enum ath79_mach_type {
ATH79_MACH_JA76PF2, /* jjPlus JA76PF2 */
ATH79_MACH_JWAP003, /* jjPlus JWAP003 */
ATH79_MACH_HORNET_UB, /* ALFA Networks Hornet-UB */
diff --git a/target/linux/ar71xx/patches-3.18/799-MIPS-ath79-add-minibox-v1-support.patch b/target/linux/ar71xx/patches-3.18/799-MIPS-ath79-add-minibox-v1-support.patch
index dab82a3df3..e77d4ef41b 100644
--- a/target/linux/ar71xx/patches-3.18/799-MIPS-ath79-add-minibox-v1-support.patch
+++ b/target/linux/ar71xx/patches-3.18/799-MIPS-ath79-add-minibox-v1-support.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -65,6 +65,7 @@ enum ath79_mach_type {
+@@ -66,6 +66,7 @@ enum ath79_mach_type {
ATH79_MACH_EPG5000, /* EnGenius EPG5000 */
ATH79_MACH_F9K1115V2, /* Belkin AC1750DB */
ATH79_MACH_GL_INET, /* GL-CONNECT GL-INET */
@@ -10,7 +10,7 @@
ATH79_MACH_JA76PF, /* jjPlus JA76PF */
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -522,6 +522,16 @@ config ATH79_MACH_EAP300V2
+@@ -531,6 +531,16 @@ config ATH79_MACH_EAP300V2
select ATH79_DEV_M25P80
select ATH79_DEV_WMAC
@@ -29,7 +29,7 @@
select SOC_AR933X
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
-@@ -76,6 +76,7 @@ obj-$(CONFIG_ATH79_MACH_EPG5000) += mach
+@@ -77,6 +77,7 @@ obj-$(CONFIG_ATH79_MACH_EPG5000) += mach
obj-$(CONFIG_ATH79_MACH_ESR1750) += mach-esr1750.o
obj-$(CONFIG_ATH79_MACH_F9K1115V2) += mach-f9k1115v2.o
obj-$(CONFIG_ATH79_MACH_GL_INET) += mach-gl-inet.o
diff --git a/target/linux/ar71xx/patches-3.18/800-MIPS-ath79-add-RB922GS-support.patch b/target/linux/ar71xx/patches-3.18/800-MIPS-ath79-add-RB922GS-support.patch
index 6f1795f24d..a387bdd33b 100644
--- a/target/linux/ar71xx/patches-3.18/800-MIPS-ath79-add-RB922GS-support.patch
+++ b/target/linux/ar71xx/patches-3.18/800-MIPS-ath79-add-RB922GS-support.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -635,6 +635,16 @@ config ATH79_MACH_RB91X
+@@ -644,6 +644,16 @@ config ATH79_MACH_RB91X
select ATH79_DEV_USB
select ATH79_ROUTERBOOT
@@ -19,7 +19,7 @@
select SOC_AR934X
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
-@@ -104,6 +104,7 @@ obj-$(CONFIG_ATH79_MACH_R6100) += mach-
+@@ -105,6 +105,7 @@ obj-$(CONFIG_ATH79_MACH_R6100) += mach-
obj-$(CONFIG_ATH79_MACH_RB4XX) += mach-rb4xx.o
obj-$(CONFIG_ATH79_MACH_RB750) += mach-rb750.o
obj-$(CONFIG_ATH79_MACH_RB91X) += mach-rb91x.o
@@ -29,7 +29,7 @@
obj-$(CONFIG_ATH79_MACH_RBSXTLITE) += mach-rbsxtlite.o
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -111,6 +111,7 @@ enum ath79_mach_type {
+@@ -112,6 +112,7 @@ enum ath79_mach_type {
ATH79_MACH_RB_750G_R3, /* MikroTik RouterBOARD 750GL */
ATH79_MACH_RB_751, /* MikroTik RouterBOARD 751 */
ATH79_MACH_RB_751G, /* Mikrotik RouterBOARD 751G */
diff --git a/target/linux/ar71xx/patches-3.18/902-unaligned_access_hacks.patch b/target/linux/ar71xx/patches-3.18/902-unaligned_access_hacks.patch
index d077b60bc8..dc0476919e 100644
--- a/target/linux/ar71xx/patches-3.18/902-unaligned_access_hacks.patch
+++ b/target/linux/ar71xx/patches-3.18/902-unaligned_access_hacks.patch
@@ -263,7 +263,7 @@
case IPV6_2292HOPOPTS:
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
-@@ -393,7 +393,7 @@ static void ip6gre_err(struct sk_buff *s
+@@ -394,7 +394,7 @@ static void ip6gre_err(struct sk_buff *s
t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr,
flags & GRE_KEY ?
@@ -272,7 +272,7 @@
p[1]);
if (t == NULL)
return;
-@@ -475,11 +475,11 @@ static int ip6gre_rcv(struct sk_buff *sk
+@@ -476,11 +476,11 @@ static int ip6gre_rcv(struct sk_buff *sk
offset += 4;
}
if (flags&GRE_KEY) {
@@ -286,7 +286,7 @@
offset += 4;
}
}
-@@ -744,7 +744,7 @@ static netdev_tx_t ip6gre_xmit2(struct s
+@@ -745,7 +745,7 @@ static netdev_tx_t ip6gre_xmit2(struct s
if (tunnel->parms.o_flags&GRE_SEQ) {
++tunnel->o_seqno;
@@ -295,7 +295,7 @@
ptr--;
}
if (tunnel->parms.o_flags&GRE_KEY) {
-@@ -840,7 +840,7 @@ static inline int ip6gre_xmit_ipv6(struc
+@@ -841,7 +841,7 @@ static inline int ip6gre_xmit_ipv6(struc
dsfield = ipv6_get_dsfield(ipv6h);
if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
diff --git a/target/linux/ar71xx/patches-3.18/903-MIPS-ath79-ubnt-rocket-m-xw-support.patch b/target/linux/ar71xx/patches-3.18/903-MIPS-ath79-ubnt-rocket-m-xw-support.patch
index 96a16c28bc..7c187ce950 100644
--- a/target/linux/ar71xx/patches-3.18/903-MIPS-ath79-ubnt-rocket-m-xw-support.patch
+++ b/target/linux/ar71xx/patches-3.18/903-MIPS-ath79-ubnt-rocket-m-xw-support.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -178,6 +178,7 @@ enum ath79_mach_type {
+@@ -179,6 +179,7 @@ enum ath79_mach_type {
ATH79_MACH_UBNT_NANO_M, /* Ubiquiti NanoStation M */
ATH79_MACH_UBNT_NANO_M_XW, /* Ubiquiti NanoStation M XW */
ATH79_MACH_UBNT_ROCKET_M, /* Ubiquiti Rocket M */
diff --git a/target/linux/ar71xx/patches-3.18/904-MIPS-ath79-bitmain-antminer-s1-support.patch b/target/linux/ar71xx/patches-3.18/904-MIPS-ath79-bitmain-antminer-s1-support.patch
index c3ee5dc899..8cd4010bdc 100644
--- a/target/linux/ar71xx/patches-3.18/904-MIPS-ath79-bitmain-antminer-s1-support.patch
+++ b/target/linux/ar71xx/patches-3.18/904-MIPS-ath79-bitmain-antminer-s1-support.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -21,6 +21,7 @@ enum ath79_mach_type {
+@@ -22,6 +22,7 @@ enum ath79_mach_type {
ATH79_MACH_ALL0258N, /* Allnet ALL0258N */
ATH79_MACH_ALL0305, /* Allnet ALL0305 */
ATH79_MACH_ALL0315N, /* Allnet ALL0315N */
@@ -10,7 +10,7 @@
ATH79_MACH_AP121_MINI, /* Atheros AP121-MINI reference board */
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -56,6 +56,16 @@ config ATH79_MACH_ALL0315N
+@@ -65,6 +65,16 @@ config ATH79_MACH_ALL0315N
select ATH79_DEV_LEDS_GPIO
select ATH79_DEV_M25P80
@@ -29,7 +29,7 @@
select SOC_AR724X
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
-@@ -42,6 +42,7 @@ obj-$(CONFIG_ATH79_MACH_ALFA_AP96) += ma
+@@ -43,6 +43,7 @@ obj-$(CONFIG_ATH79_MACH_ALFA_AP96) += ma
obj-$(CONFIG_ATH79_MACH_ALFA_NX) += mach-alfa-nx.o
obj-$(CONFIG_ATH79_MACH_ALL0258N) += mach-all0258n.o
obj-$(CONFIG_ATH79_MACH_ALL0315N) += mach-all0315n.o
diff --git a/target/linux/ar71xx/patches-3.18/905-MIPS-ath79-bitmain-antminer-s3-support.patch b/target/linux/ar71xx/patches-3.18/905-MIPS-ath79-bitmain-antminer-s3-support.patch
index c1cb70e864..12a267d13f 100644
--- a/target/linux/ar71xx/patches-3.18/905-MIPS-ath79-bitmain-antminer-s3-support.patch
+++ b/target/linux/ar71xx/patches-3.18/905-MIPS-ath79-bitmain-antminer-s3-support.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -66,6 +66,16 @@ config ATH79_MACH_ANTMINER_S1
+@@ -75,6 +75,16 @@ config ATH79_MACH_ANTMINER_S1
select ATH79_DEV_USB
select ATH79_DEV_WMAC
@@ -19,7 +19,7 @@
select SOC_AR724X
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
-@@ -43,6 +43,7 @@ obj-$(CONFIG_ATH79_MACH_ALFA_NX) += mach
+@@ -44,6 +44,7 @@ obj-$(CONFIG_ATH79_MACH_ALFA_NX) += mach
obj-$(CONFIG_ATH79_MACH_ALL0258N) += mach-all0258n.o
obj-$(CONFIG_ATH79_MACH_ALL0315N) += mach-all0315n.o
obj-$(CONFIG_ATH79_MACH_ANTMINER_S1)+= mach-antminer-s1.o
@@ -29,7 +29,7 @@
obj-$(CONFIG_ATH79_MACH_AP132) += mach-ap132.o
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -22,6 +22,7 @@ enum ath79_mach_type {
+@@ -23,6 +23,7 @@ enum ath79_mach_type {
ATH79_MACH_ALL0305, /* Allnet ALL0305 */
ATH79_MACH_ALL0315N, /* Allnet ALL0315N */
ATH79_MACH_ANTMINER_S1, /* Antminer-S1 */
diff --git a/target/linux/ar71xx/patches-3.18/906-MIPS-ath79-add-blackswift.patch b/target/linux/ar71xx/patches-3.18/906-MIPS-ath79-add-blackswift.patch
index 4d01a805a6..e12f22813e 100644
--- a/target/linux/ar71xx/patches-3.18/906-MIPS-ath79-add-blackswift.patch
+++ b/target/linux/ar71xx/patches-3.18/906-MIPS-ath79-add-blackswift.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -887,6 +887,16 @@ config ATH79_MACH_EAP7660D
+@@ -896,6 +896,16 @@ config ATH79_MACH_EAP7660D
select ATH79_DEV_LEDS_GPIO
select ATH79_DEV_M25P80
@@ -19,7 +19,7 @@
select SOC_QCA955X
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
-@@ -54,6 +54,7 @@ obj-$(CONFIG_ATH79_MACH_AP96) += mach-a
+@@ -55,6 +55,7 @@ obj-$(CONFIG_ATH79_MACH_AP96) += mach-a
obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7.o
obj-$(CONFIG_ATH79_MACH_AW_NR580) += mach-aw-nr580.o
obj-$(CONFIG_ATH79_MACH_BHU_BXU2000N2_A)+= mach-bhu-bxu2000n2-a.o
@@ -29,7 +29,7 @@
obj-$(CONFIG_ATH79_MACH_DB120) += mach-db120.o
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -37,6 +37,7 @@ enum ath79_mach_type {
+@@ -38,6 +38,7 @@ enum ath79_mach_type {
ATH79_MACH_ARCHER_C7, /* TP-LINK Archer C7 board */
ATH79_MACH_AW_NR580, /* AzureWave AW-NR580 */
ATH79_MACH_BHU_BXU2000N2_A1, /* BHU BXU2000n-2 A1 */
diff --git a/target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-WPN824N.patch b/target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-WPN824N.patch
index 2f0c964d38..d58a26fe5c 100644
--- a/target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-WPN824N.patch
+++ b/target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-WPN824N.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
-@@ -741,7 +741,7 @@ config ATH79_MACH_WNR2000
+@@ -750,7 +750,7 @@ config ATH79_MACH_WNR2000
select ATH79_DEV_WMAC
config ATH79_MACH_WNR2000_V3
@@ -11,7 +11,7 @@
select ATH79_DEV_ETH
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
-@@ -204,6 +204,7 @@ enum ath79_mach_type {
+@@ -206,6 +206,7 @@ enum ath79_mach_type {
ATH79_MACH_WNR2200, /* NETGEAR WNR2200 */
ATH79_MACH_WNR612_V2, /* NETGEAR WNR612 v2 */
ATH79_MACH_WNR1000_V2, /* NETGEAR WNR1000 v2 */
diff --git a/target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-tl-wa901nd-v4-support.patch b/target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-tl-wa901nd-v4-support.patch
index ebd9e52e19..37312adeb8 100644
--- a/target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-tl-wa901nd-v4-support.patch
+++ b/target/linux/ar71xx/patches-3.18/907-MIPS-ath79-add-tl-wa901nd-v4-support.patch
@@ -1,19 +1,19 @@
---- a/arch/mips/ath79/machtypes.h 2016-04-12 21:08:09.309541276 +0200
-+++ b/arch/mips/ath79/machtypes.h 2016-04-12 21:08:43.200013377 +0200
-@@ -152,6 +152,7 @@
- ATH79_MACH_TL_WA901ND, /* TP-LINK TL-WA901ND */
- ATH79_MACH_TL_WA901ND_V2, /* TP-LINK TL-WA901ND v2 */
- ATH79_MACH_TL_WA901ND_V3, /* TP-LINK TL-WA901ND v3 */
+--- a/arch/mips/ath79/machtypes.h
++++ b/arch/mips/ath79/machtypes.h
+@@ -152,6 +152,7 @@ enum ath79_mach_type {
+ ATH79_MACH_TL_WA901ND, /* TP-LINK TL-WA901ND */
+ ATH79_MACH_TL_WA901ND_V2, /* TP-LINK TL-WA901ND v2 */
+ ATH79_MACH_TL_WA901ND_V3, /* TP-LINK TL-WA901ND v3 */
+ ATH79_MACH_TL_WA901ND_V4, /* TP-LINK TL-WA901ND v4 */
- ATH79_MACH_TL_WDR3500, /* TP-LINK TL-WDR3500 */
- ATH79_MACH_TL_WDR4300, /* TP-LINK TL-WDR4300 */
- ATH79_MACH_TL_WDR4900_V2, /* TP-LINK TL-WDR4900 v2 */
---- a/arch/mips/ath79/Kconfig 2016-04-12 21:00:07.267269819 +0200
-+++ b/arch/mips/ath79/Kconfig 2016-04-12 21:00:08.803199911 +0200
-@@ -1023,6 +1023,15 @@
- select ATH79_DEV_M25P80
- select ATH79_DEV_WMAC
-
+ ATH79_MACH_TL_WDR3500, /* TP-LINK TL-WDR3500 */
+ ATH79_MACH_TL_WDR4300, /* TP-LINK TL-WDR4300 */
+ ATH79_MACH_TL_WDR4900_V2, /* TP-LINK TL-WDR4900 v2 */
+--- a/arch/mips/ath79/Kconfig
++++ b/arch/mips/ath79/Kconfig
+@@ -1023,6 +1023,15 @@ config ATH79_MACH_TL_WA901ND_V2
+ select ATH79_DEV_M25P80
+ select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_WA901ND_V4
+ bool "TP-LINK TL-WA901ND v4 support"
+ select SOC_QCA956X
@@ -24,11 +24,11 @@
+ select ATH79_DEV_WMAC
+
config ATH79_MACH_TL_WDR3500
- bool "TP-LINK TL-WDR3500 board support"
- select SOC_AR934X
---- a/arch/mips/ath79/Makefile 2016-04-12 21:03:21.974455904 +0200
-+++ b/arch/mips/ath79/Makefile 2016-04-12 21:02:56.115621524 +0200
-@@ -128,6 +128,7 @@
+ bool "TP-LINK TL-WDR3500 board support"
+ select SOC_AR934X
+--- a/arch/mips/ath79/Makefile
++++ b/arch/mips/ath79/Makefile
+@@ -128,6 +128,7 @@ obj-$(CONFIG_ATH79_MACH_TL_WA7210N_V2) +
obj-$(CONFIG_ATH79_MACH_TL_WA830RE_V2) += mach-tl-wa830re-v2.o
obj-$(CONFIG_ATH79_MACH_TL_WA901ND) += mach-tl-wa901nd.o
obj-$(CONFIG_ATH79_MACH_TL_WA901ND_V2) += mach-tl-wa901nd-v2.o
diff --git a/target/linux/bcm53xx/patches-3.18/150-pci-do-not-probe-too-early.patch b/target/linux/bcm53xx/patches-3.18/150-pci-do-not-probe-too-early.patch
index 2964a26faa..236b3ee204 100644
--- a/target/linux/bcm53xx/patches-3.18/150-pci-do-not-probe-too-early.patch
+++ b/target/linux/bcm53xx/patches-3.18/150-pci-do-not-probe-too-early.patch
@@ -15,7 +15,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
-@@ -2100,7 +2100,10 @@ struct pci_bus *pci_scan_root_bus(struct
+@@ -2132,7 +2132,10 @@ struct pci_bus *pci_scan_root_bus(struct
if (!found)
pci_bus_update_busn_res_end(b, max);
diff --git a/target/linux/bcm53xx/patches-3.18/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch b/target/linux/bcm53xx/patches-3.18/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch
index 08d4790e2f..64e60ce38f 100644
--- a/target/linux/bcm53xx/patches-3.18/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch
+++ b/target/linux/bcm53xx/patches-3.18/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch
@@ -49,7 +49,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
return UBI_IO_BAD_HDR_EBADMSG;
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
-@@ -743,6 +743,7 @@ extern struct mutex ubi_devices_mutex;
+@@ -747,6 +747,7 @@ extern struct mutex ubi_devices_mutex;
extern struct blocking_notifier_head ubi_notifiers;
/* attach.c */
diff --git a/target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch b/target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch
index 05835df0da..c60de181cc 100644
--- a/target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch
+++ b/target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch
@@ -90,5 +90,5 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+#endif /* CONFIG_ARCH_BCM_5301X */
+
if (!ret)
- xhci->xhc_state &= ~(XHCI_STATE_HALTED | XHCI_STATE_DYING);
-
+ /* clear state flags. Including dying, halted or removing */
+ xhci->xhc_state = 0;
diff --git a/target/linux/brcm2708/patches-3.18/0054-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch b/target/linux/brcm2708/patches-3.18/0054-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch
index 1bf26e8db3..50326c7e98 100644
--- a/target/linux/brcm2708/patches-3.18/0054-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch
+++ b/target/linux/brcm2708/patches-3.18/0054-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch
@@ -19,7 +19,7 @@ Reduces overhead when using X
module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
-@@ -1079,8 +1079,12 @@ static int usbhid_start(struct hid_devic
+@@ -1071,8 +1071,12 @@ static int usbhid_start(struct hid_devic
}
/* Change the polling interval of mice. */
diff --git a/target/linux/brcm2708/patches-3.18/0055-usb-core-make-overcurrent-messages-more-prominent.patch b/target/linux/brcm2708/patches-3.18/0055-usb-core-make-overcurrent-messages-more-prominent.patch
index 82d36f84ef..1f4ad1bab9 100644
--- a/target/linux/brcm2708/patches-3.18/0055-usb-core-make-overcurrent-messages-more-prominent.patch
+++ b/target/linux/brcm2708/patches-3.18/0055-usb-core-make-overcurrent-messages-more-prominent.patch
@@ -10,7 +10,7 @@ Hub overcurrent messages are more serious than "debug". Increase loglevel.
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
-@@ -4928,7 +4928,7 @@ static void port_event(struct usb_hub *h
+@@ -4934,7 +4934,7 @@ static void port_event(struct usb_hub *h
if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
u16 status = 0, unused;
diff --git a/target/linux/brcm63xx/patches-3.18/803-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch b/target/linux/brcm63xx/patches-3.18/803-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch
index 8b603e8b66..7a3c2f01c2 100644
--- a/target/linux/brcm63xx/patches-3.18/803-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch
+++ b/target/linux/brcm63xx/patches-3.18/803-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch
@@ -15,7 +15,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
-@@ -255,7 +255,7 @@ struct jffs2_full_dirent
+@@ -259,7 +259,7 @@ struct jffs2_full_dirent
uint32_t ino; /* == zero for unlink */
unsigned int nhash;
unsigned char type;
diff --git a/target/linux/generic/patches-3.18/099-module_arch_freeing_init-new-hook-for-archs-before-m.patch b/target/linux/generic/patches-3.18/099-module_arch_freeing_init-new-hook-for-archs-before-m.patch
index a6310c625c..2e66de29df 100644
--- a/target/linux/generic/patches-3.18/099-module_arch_freeing_init-new-hook-for-archs-before-m.patch
+++ b/target/linux/generic/patches-3.18/099-module_arch_freeing_init-new-hook-for-archs-before-m.patch
@@ -145,7 +145,7 @@ Origin: backport, https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.gi
#endif
--- a/kernel/module.c
+++ b/kernel/module.c
-@@ -1837,6 +1837,10 @@ void __weak module_arch_cleanup(struct m
+@@ -1840,6 +1840,10 @@ void __weak module_arch_cleanup(struct m
{
}
@@ -156,7 +156,7 @@ Origin: backport, https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.gi
/* Free a module, remove from lists, etc. */
static void free_module(struct module *mod)
{
-@@ -1869,6 +1873,7 @@ static void free_module(struct module *m
+@@ -1872,6 +1876,7 @@ static void free_module(struct module *m
/* This may be NULL, but that's OK */
unset_module_init_ro_nx(mod);
@@ -164,7 +164,7 @@ Origin: backport, https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.gi
module_free(mod, mod->module_init);
kfree(mod->args);
percpu_modfree(mod);
-@@ -2958,6 +2963,7 @@ static struct module *layout_and_allocat
+@@ -2978,6 +2983,7 @@ static struct module *layout_and_allocat
static void module_deallocate(struct module *mod, struct load_info *info)
{
percpu_modfree(mod);
@@ -172,8 +172,8 @@ Origin: backport, https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.gi
module_free(mod, mod->module_init);
module_free(mod, mod->module_core);
}
-@@ -3081,6 +3087,7 @@ static int do_init_module(struct module
- mod->strtab = mod->core_strtab;
+@@ -3100,6 +3106,7 @@ static int do_init_module(struct module
+ rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
#endif
unset_module_init_ro_nx(mod);
+ module_arch_freeing_init(mod);
diff --git a/target/linux/generic/patches-3.18/204-module_strip.patch b/target/linux/generic/patches-3.18/204-module_strip.patch
index deef6b0c9a..f58e0e8c5c 100644
--- a/target/linux/generic/patches-3.18/204-module_strip.patch
+++ b/target/linux/generic/patches-3.18/204-module_strip.patch
@@ -109,7 +109,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
config INIT_ALL_POSSIBLE
--- a/kernel/module.c
+++ b/kernel/module.c
-@@ -2674,6 +2674,7 @@ static struct module *setup_load_info(st
+@@ -2694,6 +2694,7 @@ static struct module *setup_load_info(st
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
{
@@ -117,7 +117,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
const char *modmagic = get_modinfo(info, "vermagic");
int err;
-@@ -2699,6 +2700,7 @@ static int check_modinfo(struct module *
+@@ -2719,6 +2720,7 @@ static int check_modinfo(struct module *
pr_warn("%s: module is from the staging directory, the quality "
"is unknown, you have been warned.\n", mod->name);
}
diff --git a/target/linux/generic/patches-3.18/494-mtd-ubi-add-EOF-marker-support.patch b/target/linux/generic/patches-3.18/494-mtd-ubi-add-EOF-marker-support.patch
index cd02c13e0c..4b5eb4568d 100644
--- a/target/linux/generic/patches-3.18/494-mtd-ubi-add-EOF-marker-support.patch
+++ b/target/linux/generic/patches-3.18/494-mtd-ubi-add-EOF-marker-support.patch
@@ -41,7 +41,7 @@
break;
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
-@@ -701,6 +701,7 @@ struct ubi_attach_info {
+@@ -705,6 +705,7 @@ struct ubi_attach_info {
int mean_ec;
uint64_t ec_sum;
int ec_count;
diff --git a/target/linux/generic/patches-3.18/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/patches-3.18/811-pci_disable_usb_common_quirks.patch
index b54d1509a5..a7bf0bb9fa 100644
--- a/target/linux/generic/patches-3.18/811-pci_disable_usb_common_quirks.patch
+++ b/target/linux/generic/patches-3.18/811-pci_disable_usb_common_quirks.patch
@@ -84,7 +84,7 @@
#endif /* __LINUX_USB_PCI_QUIRKS_H */
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
-@@ -444,7 +444,14 @@ extern int usb_hcd_pci_probe(struct pci_
+@@ -445,7 +445,14 @@ extern int usb_hcd_pci_probe(struct pci_
extern void usb_hcd_pci_remove(struct pci_dev *dev);
extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
diff --git a/target/linux/generic/patches-3.18/820-usb_add_usb_find_device_by_name.patch b/target/linux/generic/patches-3.18/820-usb_add_usb_find_device_by_name.patch
index e381cc97be..bf19f5f783 100644
--- a/target/linux/generic/patches-3.18/820-usb_add_usb_find_device_by_name.patch
+++ b/target/linux/generic/patches-3.18/820-usb_add_usb_find_device_by_name.patch
@@ -74,7 +74,7 @@
* @dev: device the buffer will be used with
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
-@@ -721,6 +721,7 @@ static inline bool usb_device_no_sg_cons
+@@ -720,6 +720,7 @@ static inline bool usb_device_no_sg_cons
return udev && udev->bus && udev->bus->no_sg_constraint;
}
diff --git a/target/linux/lantiq/patches-3.18/0001-MIPS-lantiq-add-pcie-driver.patch b/target/linux/lantiq/patches-3.18/0001-MIPS-lantiq-add-pcie-driver.patch
index 85311c21f2..4e0a51298e 100644
--- a/target/linux/lantiq/patches-3.18/0001-MIPS-lantiq-add-pcie-driver.patch
+++ b/target/linux/lantiq/patches-3.18/0001-MIPS-lantiq-add-pcie-driver.patch
@@ -5514,7 +5514,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
(transaction layer end-to-end CRC checking).
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
-@@ -1160,6 +1160,8 @@ void pci_walk_bus(struct pci_bus *top, i
+@@ -1163,6 +1163,8 @@ void pci_walk_bus(struct pci_bus *top, i
void *userdata);
int pci_cfg_space_size(struct pci_dev *dev);
unsigned char pci_bus_max_busnr(struct pci_bus *bus);
diff --git a/target/linux/oxnas/patches-3.18/320-oxnas-irqchip.patch b/target/linux/oxnas/patches-3.18/320-oxnas-irqchip.patch
index 5e130bea81..c38d6bb045 100644
--- a/target/linux/oxnas/patches-3.18/320-oxnas-irqchip.patch
+++ b/target/linux/oxnas/patches-3.18/320-oxnas-irqchip.patch
@@ -24,7 +24,7 @@
obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
-@@ -1044,6 +1044,7 @@ IRQCHIP_DECLARE(gic_400, "arm,gic-400",
+@@ -1052,6 +1052,7 @@ IRQCHIP_DECLARE(gic_400, "arm,gic-400",
IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
diff --git a/target/linux/ramips/patches-3.18/0037-USB-phy-add-ralink-SoC-driver.patch b/target/linux/ramips/patches-3.18/0037-USB-phy-add-ralink-SoC-driver.patch
index 4dc5a7528b..d4afb42eff 100644
--- a/target/linux/ramips/patches-3.18/0037-USB-phy-add-ralink-SoC-driver.patch
+++ b/target/linux/ramips/patches-3.18/0037-USB-phy-add-ralink-SoC-driver.patch
@@ -58,19 +58,19 @@
+#define RT_SYSC_REG_CLKCFG1 0x030
+#define RT_SYSC_REG_USB_PHY_CFG 0x05c
+
-+#define OFS_U2_PHY_AC0 0x00
-+#define OFS_U2_PHY_AC1 0x04
-+#define OFS_U2_PHY_AC2 0x08
-+#define OFS_U2_PHY_ACR0 0x10
-+#define OFS_U2_PHY_ACR1 0x14
-+#define OFS_U2_PHY_ACR2 0x18
-+#define OFS_U2_PHY_ACR3 0x1C
-+#define OFS_U2_PHY_ACR4 0x20
-+#define OFS_U2_PHY_AMON0 0x24
-+#define OFS_U2_PHY_DCR0 0x60
-+#define OFS_U2_PHY_DCR1 0x64
-+#define OFS_U2_PHY_DTM0 0x68
-+#define OFS_U2_PHY_DTM1 0x6C
++#define OFS_U2_PHY_AC0 0x800
++#define OFS_U2_PHY_AC1 0x804
++#define OFS_U2_PHY_AC2 0x808
++#define OFS_U2_PHY_ACR0 0x810
++#define OFS_U2_PHY_ACR1 0x814
++#define OFS_U2_PHY_ACR2 0x818
++#define OFS_U2_PHY_ACR3 0x81C
++#define OFS_U2_PHY_ACR4 0x820
++#define OFS_U2_PHY_AMON0 0x824
++#define OFS_U2_PHY_DCR0 0x860
++#define OFS_U2_PHY_DCR1 0x864
++#define OFS_U2_PHY_DTM0 0x868
++#define OFS_U2_PHY_DTM1 0x86C
+
+#define RT_RSTCTRL_UDEV BIT(25)
+#define RT_RSTCTRL_UHST BIT(22)
diff --git a/target/linux/ramips/patches-3.18/0052-i2c-MIPS-adds-ralink-I2C-driver.patch b/target/linux/ramips/patches-3.18/0052-i2c-MIPS-adds-ralink-I2C-driver.patch
index 40c61072d1..b136b52b09 100644
--- a/target/linux/ramips/patches-3.18/0052-i2c-MIPS-adds-ralink-I2C-driver.patch
+++ b/target/linux/ramips/patches-3.18/0052-i2c-MIPS-adds-ralink-I2C-driver.patch
@@ -45,7 +45,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+};
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
-@@ -711,6 +711,10 @@
+@@ -711,6 +711,10 @@ config I2C_RK3X
This driver can also be built as a module. If so, the module will
be called i2c-rk3x.
@@ -58,7 +58,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
help
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
-@@ -66,6 +66,7 @@
+@@ -66,6 +66,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
diff --git a/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch b/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch
index d52cd2e09d..4fe9f4c89e 100644
--- a/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch
+++ b/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch
@@ -1,6 +1,6 @@
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
-@@ -439,6 +439,12 @@
+@@ -439,6 +439,12 @@ config SPI_RT2880
help
This selects a driver for the Ralink RT288x/RT305x SPI Controller.
@@ -15,7 +15,7 @@
depends on ARCH_S3C24XX
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
-@@ -46,6 +46,7 @@
+@@ -46,6 +46,7 @@ obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70l
obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
@@ -25,7 +25,7 @@
obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
--- /dev/null
+++ b/drivers/spi/spi-mt7621.c
-@@ -0,0 +1,391 @@
+@@ -0,0 +1,394 @@
+/*
+ * spi-mt7621.c -- MediaTek MT7621 SPI controller driver
+ *
@@ -225,6 +225,9 @@
+ if (!buf)
+ continue;
+
++ if (t->speed_hz < speed)
++ speed = t->speed_hz;
++
+ if (WARN_ON(len + rlen > 36)) {
+ status = -EIO;
+ goto msg_done;
diff --git a/target/linux/ramips/patches-3.18/0062-mt7621-add-ECHI-OCHI-XCHI-support.patch b/target/linux/ramips/patches-3.18/0062-mt7621-add-ECHI-OCHI-XCHI-support.patch
index 4df5b3e7e5..3a8f47b104 100644
--- a/target/linux/ramips/patches-3.18/0062-mt7621-add-ECHI-OCHI-XCHI-support.patch
+++ b/target/linux/ramips/patches-3.18/0062-mt7621-add-ECHI-OCHI-XCHI-support.patch
@@ -1,6 +1,6 @@
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
-@@ -214,8 +214,13 @@ int usb_hcd_pci_probe(struct pci_dev *de
+@@ -223,8 +223,13 @@ int usb_hcd_pci_probe(struct pci_dev *de
goto disable_pci;
}
@@ -5349,7 +5349,7 @@
/* TODO: copied from ehci-hcd.c - can this be refactored? */
/*
* xhci_handshake - spin reading hc until handshake completes or fails
-@@ -199,7 +221,7 @@ int xhci_reset(struct xhci_hcd *xhci)
+@@ -200,7 +222,7 @@ int xhci_reset(struct xhci_hcd *xhci)
return ret;
}
@@ -5358,7 +5358,7 @@
static int xhci_free_msi(struct xhci_hcd *xhci)
{
int i;
-@@ -449,6 +471,11 @@ static void compliance_mode_recovery(uns
+@@ -450,6 +472,11 @@ static void compliance_mode_recovery(uns
"Attempting compliance mode recovery");
hcd = xhci->shared_hcd;
@@ -5370,7 +5370,7 @@
if (hcd->state == HC_STATE_SUSPENDED)
usb_hcd_resume_root_hub(hcd);
-@@ -498,6 +525,9 @@ static bool xhci_compliance_mode_recover
+@@ -499,6 +526,9 @@ static bool xhci_compliance_mode_recover
{
const char *dmi_product_name, *dmi_sys_vendor;
@@ -5380,7 +5380,7 @@
dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
if (!dmi_product_name || !dmi_sys_vendor)
-@@ -543,6 +573,10 @@ int xhci_init(struct usb_hcd *hcd)
+@@ -544,6 +574,10 @@ int xhci_init(struct usb_hcd *hcd)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"xHCI doesn't need link TRB QUIRK");
}
@@ -5391,7 +5391,7 @@
retval = xhci_mem_init(xhci, GFP_KERNEL);
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_init");
-@@ -627,7 +661,11 @@ int xhci_run(struct usb_hcd *hcd)
+@@ -628,7 +662,11 @@ int xhci_run(struct usb_hcd *hcd)
"// Set the interrupt modulation register");
temp = readl(&xhci->ir_set->irq_control);
temp &= ~ER_IRQ_INTERVAL_MASK;
@@ -5403,7 +5403,7 @@
writel(temp, &xhci->ir_set->irq_control);
/* Set the HCD state before we enable the irqs */
-@@ -652,6 +690,9 @@ int xhci_run(struct usb_hcd *hcd)
+@@ -653,6 +691,9 @@ int xhci_run(struct usb_hcd *hcd)
xhci_queue_vendor_command(xhci, command, 0, 0, 0,
TRB_TYPE(TRB_NEC_GET_FW));
}
@@ -5413,7 +5413,7 @@
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Finished xhci_run for USB2 roothub");
return 0;
-@@ -1650,6 +1691,14 @@ int xhci_drop_endpoint(struct usb_hcd *h
+@@ -1651,6 +1692,14 @@ int xhci_drop_endpoint(struct usb_hcd *h
u32 drop_flag;
u32 new_add_flags, new_drop_flags;
int ret;
@@ -5428,7 +5428,7 @@
ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
if (ret <= 0)
-@@ -1697,6 +1746,40 @@ int xhci_drop_endpoint(struct usb_hcd *h
+@@ -1698,6 +1747,40 @@ int xhci_drop_endpoint(struct usb_hcd *h
xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
@@ -5469,7 +5469,7 @@
xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
(unsigned int) ep->desc.bEndpointAddress,
udev->slot_id,
-@@ -1729,6 +1812,19 @@ int xhci_add_endpoint(struct usb_hcd *hc
+@@ -1730,6 +1813,19 @@ int xhci_add_endpoint(struct usb_hcd *hc
u32 new_add_flags, new_drop_flags;
struct xhci_virt_device *virt_dev;
int ret = 0;
@@ -5489,7 +5489,7 @@
ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
if (ret <= 0) {
-@@ -1795,6 +1891,56 @@ int xhci_add_endpoint(struct usb_hcd *hc
+@@ -1796,6 +1892,56 @@ int xhci_add_endpoint(struct usb_hcd *hc
return -ENOMEM;
}
@@ -5546,7 +5546,7 @@
ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs);
new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
-@@ -4465,8 +4611,14 @@ static u16 xhci_call_host_update_timeout
+@@ -4467,8 +4613,14 @@ static u16 xhci_call_host_update_timeout
u16 *timeout)
{
if (state == USB3_LPM_U1)
@@ -5561,7 +5561,7 @@
return xhci_calculate_u2_timeout(xhci, udev, desc);
return USB3_LPM_DISABLED;
-@@ -4851,7 +5003,9 @@ int xhci_gen_setup(struct usb_hcd *hcd,
+@@ -4853,7 +5005,9 @@ int xhci_gen_setup(struct usb_hcd *hcd,
hcd->self.no_sg_constraint = 1;
/* XHCI controllers don't stop the ep queue on short packets :| */
@@ -5571,9 +5571,9 @@
if (usb_hcd_is_primary_hcd(hcd)) {
xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL);
-@@ -4914,6 +5068,10 @@ int xhci_gen_setup(struct usb_hcd *hcd,
- goto error;
- xhci_dbg(xhci, "Reset complete\n");
+@@ -4926,6 +5080,10 @@ int xhci_gen_setup(struct usb_hcd *hcd,
+ if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
+ xhci->hcc_params &= ~BIT(0);
+#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM)
+ setInitialReg();
@@ -5582,7 +5582,7 @@
/* Set dma_mask and coherent_dma_mask to 64-bits,
* if xHC supports 64-bit addressing */
if (HCC_64BIT_ADDR(xhci->hcc_params) &&
-@@ -5008,8 +5166,57 @@ MODULE_DESCRIPTION(DRIVER_DESC);
+@@ -5020,8 +5178,57 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_LICENSE("GPL");
@@ -5664,7 +5664,7 @@
/* xHCI PCI Configuration Registers */
#define XHCI_SBRN_OFFSET (0x60)
-@@ -1588,8 +1603,12 @@ struct xhci_hcd {
+@@ -1590,8 +1605,12 @@ struct xhci_hcd {
/* Compliance Mode Recovery Data */
struct timer_list comp_mode_recovery_timer;
u32 port_status_u0;
@@ -5677,7 +5677,7 @@
};
/* convert between an HCD pointer and the corresponding EHCI_HCD */
-@@ -1737,6 +1756,26 @@ void xhci_urb_free_priv(struct xhci_hcd
+@@ -1739,6 +1758,26 @@ void xhci_urb_free_priv(struct xhci_hcd
void xhci_free_command(struct xhci_hcd *xhci,
struct xhci_command *command);
diff --git a/target/linux/sunxi/patches-3.18/116-dt-sunxi-update-compats-for-tempcurves.patch b/target/linux/sunxi/patches-3.18/116-dt-sunxi-update-compats-for-tempcurves.patch
deleted file mode 100644
index fe8dcdbc0a..0000000000
--- a/target/linux/sunxi/patches-3.18/116-dt-sunxi-update-compats-for-tempcurves.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From ff774d842a2bf9136b9c7ddd7f5085a9062705ac Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Mon, 16 Jun 2014 20:06:43 +0200
-Subject: [PATCH] ARM: dts: sunxi: Adjust touchscreen compatible for sun5i and
- later
-
-The touchscreen controller in the A13 and later has a different temperature
-curve than the one in the original A10, change the compatible for the A13 and
-later so that the kernel will use the correct curve.
-
-Reported-by: Tong Zhang <lovewilliam@gmail.com>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun5i-a10s.dtsi | 2 +-
- arch/arm/boot/dts/sun5i-a13.dtsi | 2 +-
- arch/arm/boot/dts/sun7i-a20.dtsi | 2 +-
- 3 files changed, 3 insertions(+), 3 deletions(-)
-
---- a/arch/arm/boot/dts/sun5i-a10s.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
-@@ -533,7 +533,7 @@
- };
-
- rtp: rtp@01c25000 {
-- compatible = "allwinner,sun4i-a10-ts";
-+ compatible = "allwinner,sun5i-a13-ts";
- reg = <0x01c25000 0x100>;
- interrupts = <29>;
- };
---- a/arch/arm/boot/dts/sun5i-a13.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
-@@ -481,7 +481,7 @@
- };
-
- rtp: rtp@01c25000 {
-- compatible = "allwinner,sun4i-a10-ts";
-+ compatible = "allwinner,sun5i-a13-ts";
- reg = <0x01c25000 0x100>;
- interrupts = <29>;
- };
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -924,7 +924,7 @@
- };
-
- rtp: rtp@01c25000 {
-- compatible = "allwinner,sun4i-a10-ts";
-+ compatible = "allwinner,sun5i-a13-ts";
- reg = <0x01c25000 0x100>;
- interrupts = <0 29 4>;
- };