diff options
author | Zoltan Herpai <wigyori@uid0.hu> | 2016-09-29 15:49:20 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-29 15:49:20 +0200 |
commit | ca3f1a614a1ee90fc67188b375888517f0c151df (patch) | |
tree | 930c456200793be1ec731e819aa0dd2e4b0b0dbf | |
parent | d6b3ca24c50047af58135ad3090f7a3a25eee35d (diff) | |
parent | f9755e28776fdce0c2136492b43380d0eefe3c5a (diff) | |
download | upstream-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
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", >k_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 = ¶ms->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>; - }; |