mirror of https://github.com/hak5/openwrt-owl.git
mac80211: backport brcmfmac patchset with driver setting concept
This prepares brcmfmac for better country handling and fixes BCM4360 support which was always failing with: [ 13.249195] brcmfmac: brcmf_pcie_download_fw_nvram: FW failed to initialize Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 48959owl
parent
296abba161
commit
f5317ed5d2
|
@ -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
|
|
@ -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;
|
|
@ -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
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
|
@ -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;
|
|
@ -0,0 +1,73 @@
|
||||||
|
From: Hante Meuleman <meuleman@broadcom.com>
|
||||||
|
Date: Wed, 17 Feb 2016 11:26:57 +0100
|
||||||
|
Subject: [PATCH] brcmfmac: use device memsize config from fw if defined
|
||||||
|
|
||||||
|
Newer type pcie devices have memory which get shared between fw and
|
||||||
|
hw. The division of this memory is done firmware compile time. As a
|
||||||
|
result the ramsize as used by driver needs to be adjusted for this.
|
||||||
|
This is done by reading the memory size from the firmware.
|
||||||
|
|
||||||
|
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
|
||||||
|
@@ -207,6 +207,10 @@ static struct brcmf_firmware_mapping brc
|
||||||
|
#define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG 0x4F4
|
||||||
|
#define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3
|
||||||
|
|
||||||
|
+/* Magic number at a magic location to find RAM size */
|
||||||
|
+#define BRCMF_RAMSIZE_MAGIC 0x534d4152 /* SMAR */
|
||||||
|
+#define BRCMF_RAMSIZE_OFFSET 0x6c
|
||||||
|
+
|
||||||
|
|
||||||
|
struct brcmf_pcie_console {
|
||||||
|
u32 base_addr;
|
||||||
|
@@ -1412,6 +1416,28 @@ static const struct brcmf_bus_ops brcmf_
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, u8 *data,
|
||||||
|
+ u32 data_len)
|
||||||
|
+{
|
||||||
|
+ __le32 *field;
|
||||||
|
+ u32 newsize;
|
||||||
|
+
|
||||||
|
+ if (data_len < BRCMF_RAMSIZE_OFFSET + 8)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ field = (__le32 *)&data[BRCMF_RAMSIZE_OFFSET];
|
||||||
|
+ if (le32_to_cpup(field) != BRCMF_RAMSIZE_MAGIC)
|
||||||
|
+ return;
|
||||||
|
+ field++;
|
||||||
|
+ newsize = le32_to_cpup(field);
|
||||||
|
+
|
||||||
|
+ brcmf_dbg(PCIE, "Found ramsize info in FW, adjusting to 0x%x\n",
|
||||||
|
+ newsize);
|
||||||
|
+ devinfo->ci->ramsize = newsize;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
|
||||||
|
u32 sharedram_addr)
|
||||||
|
@@ -1694,6 +1720,13 @@ static void brcmf_pcie_setup(struct devi
|
||||||
|
|
||||||
|
brcmf_pcie_attach(devinfo);
|
||||||
|
|
||||||
|
+ /* Some of the firmwares have the size of the memory of the device
|
||||||
|
+ * defined inside the firmware. This is because part of the memory in
|
||||||
|
+ * the device is shared and the devision is determined by FW. Parse
|
||||||
|
+ * the firmware and adjust the chip memory size now.
|
||||||
|
+ */
|
||||||
|
+ brcmf_pcie_adjust_ramsize(devinfo, (u8 *)fw->data, fw->size);
|
||||||
|
+
|
||||||
|
ret = brcmf_pcie_download_fw_nvram(devinfo, fw, nvram, nvram_len);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
|
@ -0,0 +1,58 @@
|
||||||
|
From: Hante Meuleman <meuleman@broadcom.com>
|
||||||
|
Date: Wed, 17 Feb 2016 11:26:58 +0100
|
||||||
|
Subject: [PATCH] brcmfmac: use bar1 window size as provided by pci subsystem
|
||||||
|
|
||||||
|
The PCIE bar1 window size is specified by chip. Currently the
|
||||||
|
ioremap of bar1 was using a define which always matched the size
|
||||||
|
of bar1, but newer chips can have a different bar1 sizes. With
|
||||||
|
this patch the ioremap will be called with the by chip provided
|
||||||
|
window size.
|
||||||
|
|
||||||
|
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
|
||||||
|
@@ -72,7 +72,6 @@ static struct brcmf_firmware_mapping brc
|
||||||
|
|
||||||
|
#define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */
|
||||||
|
|
||||||
|
-#define BRCMF_PCIE_TCM_MAP_SIZE (4096 * 1024)
|
||||||
|
#define BRCMF_PCIE_REG_MAP_SIZE (32 * 1024)
|
||||||
|
|
||||||
|
/* backplane addres space accessed by BAR0 */
|
||||||
|
@@ -252,7 +251,6 @@ struct brcmf_pciedev_info {
|
||||||
|
char nvram_name[BRCMF_FW_NAME_LEN];
|
||||||
|
void __iomem *regs;
|
||||||
|
void __iomem *tcm;
|
||||||
|
- u32 tcm_size;
|
||||||
|
u32 ram_base;
|
||||||
|
u32 ram_size;
|
||||||
|
struct brcmf_chip *ci;
|
||||||
|
@@ -1592,8 +1590,7 @@ static int brcmf_pcie_get_resource(struc
|
||||||
|
}
|
||||||
|
|
||||||
|
devinfo->regs = ioremap_nocache(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE);
|
||||||
|
- devinfo->tcm = ioremap_nocache(bar1_addr, BRCMF_PCIE_TCM_MAP_SIZE);
|
||||||
|
- devinfo->tcm_size = BRCMF_PCIE_TCM_MAP_SIZE;
|
||||||
|
+ devinfo->tcm = ioremap_nocache(bar1_addr, bar1_size);
|
||||||
|
|
||||||
|
if (!devinfo->regs || !devinfo->tcm) {
|
||||||
|
brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs,
|
||||||
|
@@ -1602,8 +1599,9 @@ static int brcmf_pcie_get_resource(struc
|
||||||
|
}
|
||||||
|
brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n",
|
||||||
|
devinfo->regs, (unsigned long long)bar0_addr);
|
||||||
|
- brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx\n",
|
||||||
|
- devinfo->tcm, (unsigned long long)bar1_addr);
|
||||||
|
+ brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx size 0x%x\n",
|
||||||
|
+ devinfo->tcm, (unsigned long long)bar1_addr,
|
||||||
|
+ (unsigned int)bar1_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
From: Hante Meuleman <meuleman@broadcom.com>
|
||||||
|
Date: Wed, 17 Feb 2016 11:26:59 +0100
|
||||||
|
Subject: [PATCH] brcmfmac: add support for the PCIE 4366c0 chip
|
||||||
|
|
||||||
|
A newer version of the 4366 PCIE chip has been released. Add
|
||||||
|
support for this version of the chip.
|
||||||
|
|
||||||
|
Reviewed-by: Arend Van Spriel <arend@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
|
||||||
|
@@ -53,6 +53,7 @@ BRCMF_FW_NVRAM_DEF(4358, "brcmfmac4358-p
|
||||||
|
BRCMF_FW_NVRAM_DEF(4359, "brcmfmac4359-pcie.bin", "brcmfmac4359-pcie.txt");
|
||||||
|
BRCMF_FW_NVRAM_DEF(4365B, "brcmfmac4365b-pcie.bin", "brcmfmac4365b-pcie.txt");
|
||||||
|
BRCMF_FW_NVRAM_DEF(4366B, "brcmfmac4366b-pcie.bin", "brcmfmac4366b-pcie.txt");
|
||||||
|
+BRCMF_FW_NVRAM_DEF(4366C, "brcmfmac4366c-pcie.bin", "brcmfmac4366c-pcie.txt");
|
||||||
|
BRCMF_FW_NVRAM_DEF(4371, "brcmfmac4371-pcie.bin", "brcmfmac4371-pcie.txt");
|
||||||
|
|
||||||
|
static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
|
||||||
|
@@ -66,7 +67,8 @@ static struct brcmf_firmware_mapping brc
|
||||||
|
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
|
||||||
|
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
|
||||||
|
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFFF, 4365B),
|
||||||
|
- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFFF, 4366B),
|
||||||
|
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B),
|
||||||
|
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C),
|
||||||
|
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
|
||||||
|
};
|
||||||
|
|
|
@ -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)
|
|
@ -0,0 +1,30 @@
|
||||||
|
From: Hante Meuleman <meuleman@broadcom.com>
|
||||||
|
Date: Wed, 17 Feb 2016 11:27:01 +0100
|
||||||
|
Subject: [PATCH] brcmfmac: increase timeout for tx eapol
|
||||||
|
|
||||||
|
When keys get set and updated this has to happen after eapol got
|
||||||
|
transmitted (without key or old key) before the key can be updated.
|
||||||
|
To make sure the order of sending eapol and configuring key is done
|
||||||
|
correctly a timeout for tx of eapol is applied. This timeout is set
|
||||||
|
to 50 msec, which is not always enough. Especially in AP mode and
|
||||||
|
key updates the timeout may need to be much longer because client(s)
|
||||||
|
can be in powersave. Increase the timeout from 50 to 950 msec.
|
||||||
|
|
||||||
|
Reviewed-by: Arend Van Spriel <arend@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/core.c
|
||||||
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||||
|
@@ -42,7 +42,7 @@ 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(50)
|
||||||
|
+#define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950)
|
||||||
|
|
||||||
|
/* AMPDU rx reordering definitions */
|
||||||
|
#define BRCMF_RXREORDER_FLOWID_OFFSET 0
|
|
@ -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 */
|
|
@ -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_ */
|
|
@ -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 */
|
|
@ -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:
|
|
@ -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 */
|
|
@ -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)
|
|
@ -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,
|
|
@ -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
|
|
@ -13,8 +13,8 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||||
|
|
||||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
||||||
@@ -1332,6 +1332,7 @@ static int __init brcmfmac_module_init(v
|
@@ -1417,6 +1417,7 @@ int __init brcmf_core_init(void)
|
||||||
#endif
|
{
|
||||||
if (!schedule_work(&brcmf_driver_work))
|
if (!schedule_work(&brcmf_driver_work))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
+ flush_work(&brcmf_driver_work);
|
+ flush_work(&brcmf_driver_work);
|
||||||
|
|
|
@ -10,7 +10,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||||
|
|
||||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
||||||
@@ -615,9 +615,37 @@ static struct wireless_dev *brcmf_cfg802
|
@@ -636,9 +636,37 @@ static struct wireless_dev *brcmf_cfg802
|
||||||
u32 *flags,
|
u32 *flags,
|
||||||
struct vif_params *params)
|
struct vif_params *params)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue