mac80211: backport some brcmfmac patches
There are two important patches in this patchset: updating read pointer quicker & rework of .get_station(). There are few more upstream patches that are p2p-related and weren't backported in this commit. Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 46084
This commit is contained in:
parent
167a2dc12e
commit
1909a42ad4
8 changed files with 892 additions and 0 deletions
|
@ -0,0 +1,109 @@
|
|||
From: Hante Meuleman <meuleman@broadcom.com>
|
||||
Date: Mon, 8 Jun 2015 14:38:32 +0200
|
||||
Subject: [PATCH] brcmfmac: Update msgbuf read pointer quicker.
|
||||
|
||||
On device to host data using msgbuf the read pointer gets updated
|
||||
once all data is processed. Updating this pointer more frequently
|
||||
allows the firmware to add more data quicker. This will result in
|
||||
slightly higher and more stable throughput on CPU bounded host
|
||||
processors.
|
||||
|
||||
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/brcm80211/brcmfmac/commonring.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
|
||||
@@ -223,8 +223,6 @@ void brcmf_commonring_write_cancel(struc
|
||||
void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
u16 *n_items)
|
||||
{
|
||||
- void *ret_addr;
|
||||
-
|
||||
if (commonring->cr_update_wptr)
|
||||
commonring->cr_update_wptr(commonring->cr_ctx);
|
||||
|
||||
@@ -235,19 +233,18 @@ void *brcmf_commonring_get_read_ptr(stru
|
||||
if (*n_items == 0)
|
||||
return NULL;
|
||||
|
||||
- ret_addr = commonring->buf_addr +
|
||||
- (commonring->r_ptr * commonring->item_len);
|
||||
-
|
||||
- commonring->r_ptr += *n_items;
|
||||
- if (commonring->r_ptr == commonring->depth)
|
||||
- commonring->r_ptr = 0;
|
||||
-
|
||||
- return ret_addr;
|
||||
+ return commonring->buf_addr +
|
||||
+ (commonring->r_ptr * commonring->item_len);
|
||||
}
|
||||
|
||||
|
||||
-int brcmf_commonring_read_complete(struct brcmf_commonring *commonring)
|
||||
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
|
||||
+ u16 n_items)
|
||||
{
|
||||
+ commonring->r_ptr += n_items;
|
||||
+ if (commonring->r_ptr == commonring->depth)
|
||||
+ commonring->r_ptr = 0;
|
||||
+
|
||||
if (commonring->cr_write_rptr)
|
||||
return commonring->cr_write_rptr(commonring->cr_ctx);
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
|
||||
@@ -62,7 +62,8 @@ void brcmf_commonring_write_cancel(struc
|
||||
u16 n_items);
|
||||
void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
u16 *n_items);
|
||||
-int brcmf_commonring_read_complete(struct brcmf_commonring *commonring);
|
||||
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
|
||||
+ u16 n_items);
|
||||
|
||||
#define brcmf_commonring_n_items(commonring) (commonring->depth)
|
||||
#define brcmf_commonring_len_item(commonring) (commonring->item_len)
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -75,6 +75,8 @@
|
||||
|
||||
#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96
|
||||
#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32
|
||||
+#define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS 48
|
||||
+
|
||||
|
||||
struct msgbuf_common_hdr {
|
||||
u8 msgtype;
|
||||
@@ -1257,19 +1259,27 @@ static void brcmf_msgbuf_process_rx(stru
|
||||
{
|
||||
void *buf;
|
||||
u16 count;
|
||||
+ u16 processed;
|
||||
|
||||
again:
|
||||
buf = brcmf_commonring_get_read_ptr(commonring, &count);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
+ processed = 0;
|
||||
while (count) {
|
||||
brcmf_msgbuf_process_msgtype(msgbuf,
|
||||
buf + msgbuf->rx_dataoffset);
|
||||
buf += brcmf_commonring_len_item(commonring);
|
||||
+ processed++;
|
||||
+ if (processed == BRCMF_MSGBUF_UPDATE_RX_PTR_THRS) {
|
||||
+ brcmf_commonring_read_complete(commonring, processed);
|
||||
+ processed = 0;
|
||||
+ }
|
||||
count--;
|
||||
}
|
||||
- brcmf_commonring_read_complete(commonring);
|
||||
+ if (processed)
|
||||
+ brcmf_commonring_read_complete(commonring, processed);
|
||||
|
||||
if (commonring->r_ptr == 0)
|
||||
goto again;
|
|
@ -0,0 +1,39 @@
|
|||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Mon, 8 Jun 2015 14:38:33 +0200
|
||||
Subject: [PATCH] brcmfmac: remove chipinfo debugfs entry
|
||||
|
||||
The information provided by chipinfo is also provided by the
|
||||
revinfo debugfs entry. Removing it from debugfs.
|
||||
|
||||
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/brcm80211/brcmfmac/debug.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
|
||||
@@ -41,15 +41,6 @@ void brcmf_debugfs_exit(void)
|
||||
root_folder = NULL;
|
||||
}
|
||||
|
||||
-static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
|
||||
-{
|
||||
- struct brcmf_bus *bus = dev_get_drvdata(seq->private);
|
||||
-
|
||||
- seq_printf(seq, "chip: %x(%u) rev %u\n",
|
||||
- bus->chip, bus->chip, bus->chiprev);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
int brcmf_debugfs_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct device *dev = drvr->bus_if->dev;
|
||||
@@ -58,7 +49,6 @@ int brcmf_debugfs_attach(struct brcmf_pu
|
||||
return -ENODEV;
|
||||
|
||||
drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
|
||||
- brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
|
||||
|
||||
return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Mon, 8 Jun 2015 14:38:34 +0200
|
||||
Subject: [PATCH] brcmfmac: remove watchdog reset from
|
||||
brcmf_pcie_buscoreprep()
|
||||
|
||||
The watchdog reset as done in brcmf_pcie_buscoreprep() is not
|
||||
sufficient. It needs to modify PCIe core registers as well
|
||||
which is properly done by brcmf_pcie_reset_device() after the
|
||||
chip recognition is done. So the faulty watchdog reset can be
|
||||
removed as it was causing driver reload to fail and hang the
|
||||
system requiring a power-cycle. Instead the call to to the
|
||||
brcmf_pcie_reset_device() function is done twice in the unload.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
@@ -1629,20 +1629,7 @@ static void brcmf_pcie_buscore_write32(v
|
||||
|
||||
static int brcmf_pcie_buscoreprep(void *ctx)
|
||||
{
|
||||
- struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
|
||||
- int err;
|
||||
-
|
||||
- err = brcmf_pcie_get_resource(devinfo);
|
||||
- if (err == 0) {
|
||||
- /* Set CC watchdog to reset all the cores on the chip to bring
|
||||
- * back dongle to a sane state.
|
||||
- */
|
||||
- brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE,
|
||||
- watchdog), 4);
|
||||
- msleep(100);
|
||||
- }
|
||||
-
|
||||
- return err;
|
||||
+ return brcmf_pcie_get_resource(ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -1824,6 +1811,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
|
||||
brcmf_pcie_intr_disable(devinfo);
|
||||
|
||||
brcmf_detach(&pdev->dev);
|
||||
+ brcmf_pcie_reset_device(devinfo);
|
||||
|
||||
kfree(bus->bus_priv.pcie);
|
||||
kfree(bus->msgbuf->flowrings);
|
|
@ -0,0 +1,69 @@
|
|||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Mon, 8 Jun 2015 14:38:35 +0200
|
||||
Subject: [PATCH] brcmfmac: use debugfs_create_devm_seqfile() helper
|
||||
function
|
||||
|
||||
Some time ago the function debugfs_create_devm_seqfile() was
|
||||
introduced in debugfs. The caller simply needs to provide a
|
||||
device pointer and read function. The function brcmf_debugfs_add_entry()
|
||||
is now simply a wrapper only doing the work for CONFIG_BRCMDBG.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
|
||||
@@ -64,44 +64,12 @@ struct dentry *brcmf_debugfs_get_devdir(
|
||||
return drvr->dbgfs_dir;
|
||||
}
|
||||
|
||||
-struct brcmf_debugfs_entry {
|
||||
- int (*read)(struct seq_file *seq, void *data);
|
||||
- struct brcmf_pub *drvr;
|
||||
-};
|
||||
-
|
||||
-static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
|
||||
-{
|
||||
- struct brcmf_debugfs_entry *entry = inode->i_private;
|
||||
-
|
||||
- return single_open(f, entry->read, entry->drvr->bus_if->dev);
|
||||
-}
|
||||
-
|
||||
-static const struct file_operations brcmf_debugfs_def_ops = {
|
||||
- .owner = THIS_MODULE,
|
||||
- .open = brcmf_debugfs_entry_open,
|
||||
- .release = single_release,
|
||||
- .read = seq_read,
|
||||
- .llseek = seq_lseek
|
||||
-};
|
||||
-
|
||||
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
|
||||
int (*read_fn)(struct seq_file *seq, void *data))
|
||||
{
|
||||
- struct dentry *dentry = drvr->dbgfs_dir;
|
||||
- struct brcmf_debugfs_entry *entry;
|
||||
-
|
||||
- if (IS_ERR_OR_NULL(dentry))
|
||||
- return -ENOENT;
|
||||
-
|
||||
- entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
|
||||
- if (!entry)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- entry->read = read_fn;
|
||||
- entry->drvr = drvr;
|
||||
-
|
||||
- dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
|
||||
- &brcmf_debugfs_def_ops);
|
||||
+ struct dentry *e;
|
||||
|
||||
- return PTR_ERR_OR_ZERO(dentry);
|
||||
+ e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn,
|
||||
+ drvr->dbgfs_dir, read_fn);
|
||||
+ return PTR_ERR_OR_ZERO(e);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
From: Pontus Fuchs <pontusf@broadcom.com>
|
||||
Date: Thu, 11 Jun 2015 00:12:17 +0200
|
||||
Subject: [PATCH] brcmfmac: Check if firmware supports p2p
|
||||
|
||||
Add a feature flag to reflect the firmware's p2p capability.
|
||||
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Pontus Fuchs <pontusf@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
|
||||
@@ -129,6 +129,7 @@ void brcmf_feat_attach(struct brcmf_pub
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
|
||||
if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
|
||||
brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
|
||||
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
|
||||
|
||||
/* set chip related quirks */
|
||||
switch (drvr->bus_if->chip) {
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
|
||||
@@ -23,12 +23,14 @@
|
||||
* MCHAN: multi-channel for concurrent P2P.
|
||||
* PNO: preferred network offload.
|
||||
* WOWL: Wake-On-WLAN.
|
||||
+ * P2P: peer-to-peer
|
||||
*/
|
||||
#define BRCMF_FEAT_LIST \
|
||||
BRCMF_FEAT_DEF(MBSS) \
|
||||
BRCMF_FEAT_DEF(MCHAN) \
|
||||
BRCMF_FEAT_DEF(PNO) \
|
||||
- BRCMF_FEAT_DEF(WOWL)
|
||||
+ BRCMF_FEAT_DEF(WOWL) \
|
||||
+ BRCMF_FEAT_DEF(P2P)
|
||||
/*
|
||||
* Quirks:
|
||||
*
|
|
@ -0,0 +1,198 @@
|
|||
From: Pontus Fuchs <pontusf@broadcom.com>
|
||||
Date: Thu, 11 Jun 2015 00:12:18 +0200
|
||||
Subject: [PATCH] brcmfmac: Build wiphy mode and interface combinations
|
||||
dynamically
|
||||
|
||||
Switch from using semi hard coded interface combinations. This makes
|
||||
it easier to announce what the firmware actually supports. This fixes
|
||||
the case where brcmfmac announces p2p but the firmware doesn't
|
||||
support it.
|
||||
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Pontus Fuchs <pontusf@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -52,8 +52,6 @@
|
||||
#define BRCMF_PNO_SCAN_COMPLETE 1
|
||||
#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
||||
|
||||
-#define BRCMF_IFACE_MAX_CNT 3
|
||||
-
|
||||
#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
|
||||
#define WPA_OUI_TYPE 1
|
||||
#define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */
|
||||
@@ -5639,53 +5637,6 @@ static int brcmf_setup_wiphybands(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = {
|
||||
- {
|
||||
- .max = 1,
|
||||
- .types = BIT(NL80211_IFTYPE_STATION) |
|
||||
- BIT(NL80211_IFTYPE_ADHOC)
|
||||
- },
|
||||
- {
|
||||
- .max = 4,
|
||||
- .types = BIT(NL80211_IFTYPE_AP)
|
||||
- },
|
||||
- {
|
||||
- .max = 1,
|
||||
- .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
- BIT(NL80211_IFTYPE_P2P_GO)
|
||||
- },
|
||||
- {
|
||||
- .max = 1,
|
||||
- .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = {
|
||||
- {
|
||||
- .max = 2,
|
||||
- .types = BIT(NL80211_IFTYPE_STATION) |
|
||||
- BIT(NL80211_IFTYPE_ADHOC) |
|
||||
- BIT(NL80211_IFTYPE_AP)
|
||||
- },
|
||||
- {
|
||||
- .max = 1,
|
||||
- .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
- BIT(NL80211_IFTYPE_P2P_GO)
|
||||
- },
|
||||
- {
|
||||
- .max = 1,
|
||||
- .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
- }
|
||||
-};
|
||||
-static struct ieee80211_iface_combination brcmf_iface_combos[] = {
|
||||
- {
|
||||
- .max_interfaces = BRCMF_IFACE_MAX_CNT,
|
||||
- .num_different_channels = 1,
|
||||
- .n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss),
|
||||
- .limits = brcmf_iface_limits_sbss,
|
||||
- }
|
||||
-};
|
||||
-
|
||||
static const struct ieee80211_txrx_stypes
|
||||
brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
|
||||
[NL80211_IFTYPE_STATION] = {
|
||||
@@ -5715,6 +5666,67 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
|
||||
}
|
||||
};
|
||||
|
||||
+static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
+{
|
||||
+ struct ieee80211_iface_combination *combo = NULL;
|
||||
+ struct ieee80211_iface_limit *limits = NULL;
|
||||
+ int i = 0, max_iface_cnt;
|
||||
+
|
||||
+ combo = kzalloc(sizeof(*combo), GFP_KERNEL);
|
||||
+ if (!combo)
|
||||
+ goto err;
|
||||
+
|
||||
+ limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
|
||||
+ if (!limits)
|
||||
+ goto err;
|
||||
+
|
||||
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
+ BIT(NL80211_IFTYPE_ADHOC) |
|
||||
+ BIT(NL80211_IFTYPE_AP);
|
||||
+
|
||||
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
|
||||
+ combo->num_different_channels = 2;
|
||||
+ else
|
||||
+ combo->num_different_channels = 1;
|
||||
+
|
||||
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
|
||||
+ limits[i].max = 1;
|
||||
+ limits[i++].types = BIT(NL80211_IFTYPE_STATION);
|
||||
+ limits[i].max = 4;
|
||||
+ limits[i++].types = BIT(NL80211_IFTYPE_AP);
|
||||
+ max_iface_cnt = 5;
|
||||
+ } else {
|
||||
+ limits[i].max = 2;
|
||||
+ limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
|
||||
+ BIT(NL80211_IFTYPE_AP);
|
||||
+ max_iface_cnt = 2;
|
||||
+ }
|
||||
+
|
||||
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
|
||||
+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
+ BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
+ BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
+ limits[i].max = 1;
|
||||
+ limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
+ BIT(NL80211_IFTYPE_P2P_GO);
|
||||
+ limits[i].max = 1;
|
||||
+ limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
+ max_iface_cnt += 2;
|
||||
+ }
|
||||
+ combo->max_interfaces = max_iface_cnt;
|
||||
+ combo->limits = limits;
|
||||
+ combo->n_limits = i;
|
||||
+
|
||||
+ wiphy->iface_combinations = combo;
|
||||
+ wiphy->n_iface_combinations = 1;
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ kfree(limits);
|
||||
+ kfree(combo);
|
||||
+ return -ENOMEM;
|
||||
+}
|
||||
+
|
||||
static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
|
||||
{
|
||||
/* scheduled scan settings */
|
||||
@@ -5745,7 +5757,6 @@ static void brcmf_wiphy_wowl_params(stru
|
||||
static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
{
|
||||
struct ieee80211_supported_band *band;
|
||||
- struct ieee80211_iface_combination ifc_combo;
|
||||
__le32 bandlist[3];
|
||||
u32 n_bands;
|
||||
int err, i;
|
||||
@@ -5753,24 +5764,11 @@ static int brcmf_setup_wiphy(struct wiph
|
||||
wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
|
||||
wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
|
||||
wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
|
||||
- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
- BIT(NL80211_IFTYPE_ADHOC) |
|
||||
- BIT(NL80211_IFTYPE_AP) |
|
||||
- BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
- BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
- BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
- /* need VSDB firmware feature for concurrent channels */
|
||||
- ifc_combo = brcmf_iface_combos[0];
|
||||
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
|
||||
- ifc_combo.num_different_channels = 2;
|
||||
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
|
||||
- ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss),
|
||||
- ifc_combo.limits = brcmf_iface_limits_mbss;
|
||||
- }
|
||||
- wiphy->iface_combinations = kmemdup(&ifc_combo,
|
||||
- sizeof(ifc_combo),
|
||||
- GFP_KERNEL);
|
||||
- wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
|
||||
+
|
||||
+ err = brcmf_setup_ifmodes(wiphy, ifp);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
||||
wiphy->cipher_suites = __wl_cipher_suites;
|
||||
wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
|
||||
@@ -6035,6 +6033,8 @@ static void brcmf_free_wiphy(struct wiph
|
||||
if (!wiphy)
|
||||
return;
|
||||
|
||||
+ if (wiphy->iface_combinations)
|
||||
+ kfree(wiphy->iface_combinations->limits);
|
||||
kfree(wiphy->iface_combinations);
|
||||
if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
|
||||
kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
|
|
@ -0,0 +1,326 @@
|
|||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Thu, 11 Jun 2015 00:12:19 +0200
|
||||
Subject: [PATCH] brcmfmac: rework .get_station() callback
|
||||
|
||||
The .get_station() cfg80211 callback is used in several scenarios. In
|
||||
managed mode it can obtain information about the access-point and its
|
||||
BSS parameters. In managed mode it can also obtain information about
|
||||
TDLS peers. In AP mode it can obtain information about connected
|
||||
clients.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -2395,27 +2395,80 @@ brcmf_cfg80211_reconfigure_wep(struct br
|
||||
brcmf_err("set wsec error (%d)\n", err);
|
||||
}
|
||||
|
||||
+static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
|
||||
+{
|
||||
+ struct nl80211_sta_flag_update *sfu;
|
||||
+
|
||||
+ brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags);
|
||||
+ si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
|
||||
+ sfu = &si->sta_flags;
|
||||
+ sfu->mask = BIT(NL80211_STA_FLAG_WME) |
|
||||
+ BIT(NL80211_STA_FLAG_AUTHENTICATED) |
|
||||
+ BIT(NL80211_STA_FLAG_ASSOCIATED) |
|
||||
+ BIT(NL80211_STA_FLAG_AUTHORIZED);
|
||||
+ if (fw_sta_flags & BRCMF_STA_WME)
|
||||
+ sfu->set |= BIT(NL80211_STA_FLAG_WME);
|
||||
+ if (fw_sta_flags & BRCMF_STA_AUTHE)
|
||||
+ sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
|
||||
+ if (fw_sta_flags & BRCMF_STA_ASSOC)
|
||||
+ sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
|
||||
+ if (fw_sta_flags & BRCMF_STA_AUTHO)
|
||||
+ sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
|
||||
+}
|
||||
+
|
||||
+static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
|
||||
+{
|
||||
+ struct {
|
||||
+ __le32 len;
|
||||
+ struct brcmf_bss_info_le bss_le;
|
||||
+ } *buf;
|
||||
+ u16 capability;
|
||||
+ int err;
|
||||
+
|
||||
+ buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
|
||||
+ if (!buf)
|
||||
+ return;
|
||||
+
|
||||
+ buf->len = cpu_to_le32(WL_BSS_INFO_MAX);
|
||||
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,
|
||||
+ WL_BSS_INFO_MAX);
|
||||
+ if (err) {
|
||||
+ brcmf_err("Failed to get bss info (%d)\n", err);
|
||||
+ return;
|
||||
+ }
|
||||
+ si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
|
||||
+ si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
|
||||
+ si->bss_param.dtim_period = buf->bss_le.dtim_period;
|
||||
+ capability = le16_to_cpu(buf->bss_le.capability);
|
||||
+ if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT)
|
||||
+ si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
|
||||
+ if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
+ si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
|
||||
+ if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
+ si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
|
||||
+}
|
||||
+
|
||||
static s32
|
||||
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
||||
const u8 *mac, struct station_info *sinfo)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
- struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
|
||||
- struct brcmf_scb_val_le scb_val;
|
||||
- int rssi;
|
||||
- s32 rate;
|
||||
s32 err = 0;
|
||||
- u8 *bssid = profile->bssid;
|
||||
struct brcmf_sta_info_le sta_info_le;
|
||||
- u32 beacon_period;
|
||||
- u32 dtim_period;
|
||||
+ u32 sta_flags;
|
||||
+ u32 is_tdls_peer;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
|
||||
if (!check_vif_up(ifp->vif))
|
||||
return -EIO;
|
||||
|
||||
- if (brcmf_is_apmode(ifp->vif)) {
|
||||
- memcpy(&sta_info_le, mac, ETH_ALEN);
|
||||
+ memset(&sta_info_le, 0, sizeof(sta_info_le));
|
||||
+ memcpy(&sta_info_le, mac, ETH_ALEN);
|
||||
+ err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",
|
||||
+ &sta_info_le,
|
||||
+ sizeof(sta_info_le));
|
||||
+ is_tdls_peer = !err;
|
||||
+ if (err) {
|
||||
err = brcmf_fil_iovar_data_get(ifp, "sta_info",
|
||||
&sta_info_le,
|
||||
sizeof(sta_info_le));
|
||||
@@ -2423,73 +2476,48 @@ brcmf_cfg80211_get_station(struct wiphy
|
||||
brcmf_err("GET STA INFO failed, %d\n", err);
|
||||
goto done;
|
||||
}
|
||||
- sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
|
||||
- sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
|
||||
- if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
|
||||
- sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
|
||||
- sinfo->connected_time = le32_to_cpu(sta_info_le.in);
|
||||
- }
|
||||
- brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
|
||||
- sinfo->inactive_time, sinfo->connected_time);
|
||||
- } else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) {
|
||||
- if (memcmp(mac, bssid, ETH_ALEN)) {
|
||||
- brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
|
||||
- mac, bssid);
|
||||
- err = -ENOENT;
|
||||
- goto done;
|
||||
- }
|
||||
- /* Report the current tx rate */
|
||||
- err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
|
||||
- if (err) {
|
||||
- brcmf_err("Could not get rate (%d)\n", err);
|
||||
- goto done;
|
||||
- } else {
|
||||
+ }
|
||||
+ brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
|
||||
+ sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
|
||||
+ sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
|
||||
+ sta_flags = le32_to_cpu(sta_info_le.flags);
|
||||
+ brcmf_convert_sta_flags(sta_flags, sinfo);
|
||||
+ sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
+ if (is_tdls_peer)
|
||||
+ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
+ else
|
||||
+ sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
+ if (sta_flags & BRCMF_STA_ASSOC) {
|
||||
+ sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
|
||||
+ sinfo->connected_time = le32_to_cpu(sta_info_le.in);
|
||||
+ brcmf_fill_bss_param(ifp, sinfo);
|
||||
+ }
|
||||
+ if (sta_flags & BRCMF_STA_SCBSTATS) {
|
||||
+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED);
|
||||
+ sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures);
|
||||
+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
|
||||
+ sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts);
|
||||
+ sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts);
|
||||
+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
|
||||
+ sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts);
|
||||
+ sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
|
||||
+ if (sinfo->tx_packets) {
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
|
||||
- sinfo->txrate.legacy = rate * 5;
|
||||
- brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
|
||||
+ sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate);
|
||||
+ sinfo->txrate.legacy /= 100;
|
||||
}
|
||||
-
|
||||
- if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
|
||||
- &ifp->vif->sme_state)) {
|
||||
- memset(&scb_val, 0, sizeof(scb_val));
|
||||
- err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
|
||||
- &scb_val, sizeof(scb_val));
|
||||
- if (err) {
|
||||
- brcmf_err("Could not get rssi (%d)\n", err);
|
||||
- goto done;
|
||||
- } else {
|
||||
- rssi = le32_to_cpu(scb_val.val);
|
||||
- sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
|
||||
- sinfo->signal = rssi;
|
||||
- brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
|
||||
- }
|
||||
- err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD,
|
||||
- &beacon_period);
|
||||
- if (err) {
|
||||
- brcmf_err("Could not get beacon period (%d)\n",
|
||||
- err);
|
||||
- goto done;
|
||||
- } else {
|
||||
- sinfo->bss_param.beacon_interval =
|
||||
- beacon_period;
|
||||
- brcmf_dbg(CONN, "Beacon peroid %d\n",
|
||||
- beacon_period);
|
||||
- }
|
||||
- err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD,
|
||||
- &dtim_period);
|
||||
- if (err) {
|
||||
- brcmf_err("Could not get DTIM period (%d)\n",
|
||||
- err);
|
||||
- goto done;
|
||||
- } else {
|
||||
- sinfo->bss_param.dtim_period = dtim_period;
|
||||
- brcmf_dbg(CONN, "DTIM peroid %d\n",
|
||||
- dtim_period);
|
||||
- }
|
||||
- sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
|
||||
+ if (sinfo->rx_packets) {
|
||||
+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
|
||||
+ sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate);
|
||||
+ sinfo->rxrate.legacy /= 100;
|
||||
+ }
|
||||
+ if (le16_to_cpu(sta_info_le.ver) >= 4) {
|
||||
+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
|
||||
+ sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
|
||||
+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
|
||||
+ sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
|
||||
}
|
||||
- } else
|
||||
- err = -EPERM;
|
||||
+ }
|
||||
done:
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
return err;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
|
||||
@@ -32,7 +32,11 @@
|
||||
#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
|
||||
#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
|
||||
|
||||
-#define BRCMF_STA_ASSOC 0x10 /* Associated */
|
||||
+#define BRCMF_STA_WME 0x00000002 /* WMM association */
|
||||
+#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
|
||||
+#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
|
||||
+#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
|
||||
+#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
|
||||
|
||||
/* size of brcmf_scan_params not including variable length array */
|
||||
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
|
||||
@@ -113,6 +117,7 @@
|
||||
#define BRCMF_WOWL_MAXPATTERNSIZE 128
|
||||
|
||||
#define BRCMF_COUNTRY_BUF_SZ 4
|
||||
+#define BRCMF_ANT_MAX 4
|
||||
|
||||
/* join preference types for join_pref iovar */
|
||||
enum brcmf_join_pref_types {
|
||||
@@ -456,25 +461,61 @@ struct brcmf_channel_info_le {
|
||||
};
|
||||
|
||||
struct brcmf_sta_info_le {
|
||||
- __le16 ver; /* version of this struct */
|
||||
- __le16 len; /* length in bytes of this structure */
|
||||
- __le16 cap; /* sta's advertised capabilities */
|
||||
- __le32 flags; /* flags defined below */
|
||||
- __le32 idle; /* time since data pkt rx'd from sta */
|
||||
- u8 ea[ETH_ALEN]; /* Station address */
|
||||
- __le32 count; /* # rates in this set */
|
||||
- u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
|
||||
+ __le16 ver; /* version of this struct */
|
||||
+ __le16 len; /* length in bytes of this structure */
|
||||
+ __le16 cap; /* sta's advertised capabilities */
|
||||
+ __le32 flags; /* flags defined below */
|
||||
+ __le32 idle; /* time since data pkt rx'd from sta */
|
||||
+ u8 ea[ETH_ALEN]; /* Station address */
|
||||
+ __le32 count; /* # rates in this set */
|
||||
+ u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
|
||||
/* w/hi bit set if basic */
|
||||
- __le32 in; /* seconds elapsed since associated */
|
||||
- __le32 listen_interval_inms; /* Min Listen interval in ms for STA */
|
||||
- __le32 tx_pkts; /* # of packets transmitted */
|
||||
- __le32 tx_failures; /* # of packets failed */
|
||||
- __le32 rx_ucast_pkts; /* # of unicast packets received */
|
||||
- __le32 rx_mcast_pkts; /* # of multicast packets received */
|
||||
- __le32 tx_rate; /* Rate of last successful tx frame */
|
||||
- __le32 rx_rate; /* Rate of last successful rx frame */
|
||||
- __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
|
||||
- __le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
+ __le32 in; /* seconds elapsed since associated */
|
||||
+ __le32 listen_interval_inms; /* Min Listen interval in ms for STA */
|
||||
+ __le32 tx_pkts; /* # of packets transmitted */
|
||||
+ __le32 tx_failures; /* # of packets failed */
|
||||
+ __le32 rx_ucast_pkts; /* # of unicast packets received */
|
||||
+ __le32 rx_mcast_pkts; /* # of multicast packets received */
|
||||
+ __le32 tx_rate; /* Rate of last successful tx frame */
|
||||
+ __le32 rx_rate; /* Rate of last successful rx frame */
|
||||
+ __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
|
||||
+ __le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
+ __le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */
|
||||
+ __le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */
|
||||
+ __le32 tx_mcast_pkts; /* # of mcast pkts txed */
|
||||
+ __le64 tx_tot_bytes; /* data bytes txed (ucast + mcast) */
|
||||
+ __le64 rx_tot_bytes; /* data bytes recvd (ucast + mcast) */
|
||||
+ __le64 tx_ucast_bytes; /* data bytes txed (ucast) */
|
||||
+ __le64 tx_mcast_bytes; /* # data bytes txed (mcast) */
|
||||
+ __le64 rx_ucast_bytes; /* data bytes recvd (ucast) */
|
||||
+ __le64 rx_mcast_bytes; /* data bytes recvd (mcast) */
|
||||
+ s8 rssi[BRCMF_ANT_MAX]; /* per antenna rssi */
|
||||
+ s8 nf[BRCMF_ANT_MAX]; /* per antenna noise floor */
|
||||
+ __le16 aid; /* association ID */
|
||||
+ __le16 ht_capabilities; /* advertised ht caps */
|
||||
+ __le16 vht_flags; /* converted vht flags */
|
||||
+ __le32 tx_pkts_retry_cnt; /* # of frames where a retry was
|
||||
+ * exhausted.
|
||||
+ */
|
||||
+ __le32 tx_pkts_retry_exhausted; /* # of user frames where a retry
|
||||
+ * was exhausted
|
||||
+ */
|
||||
+ s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last
|
||||
+ * received data frame.
|
||||
+ */
|
||||
+ /* TX WLAN retry/failure statistics:
|
||||
+ * Separated for host requested frames and locally generated frames.
|
||||
+ * Include unicast frame only where the retries/failures can be counted.
|
||||
+ */
|
||||
+ __le32 tx_pkts_total; /* # user frames sent successfully */
|
||||
+ __le32 tx_pkts_retries; /* # user frames retries */
|
||||
+ __le32 tx_pkts_fw_total; /* # FW generated sent successfully */
|
||||
+ __le32 tx_pkts_fw_retries; /* # retries for FW generated frames */
|
||||
+ __le32 tx_pkts_fw_retry_exhausted; /* # FW generated where a retry
|
||||
+ * was exhausted
|
||||
+ */
|
||||
+ __le32 rx_pkts_retried; /* # rx with retry bit set */
|
||||
+ __le32 tx_rate_fallback; /* lowest fallback TX rate */
|
||||
};
|
||||
|
||||
struct brcmf_chanspec_list {
|
|
@ -0,0 +1,56 @@
|
|||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Thu, 11 Jun 2015 00:12:20 +0200
|
||||
Subject: [PATCH] brcmfmac: have sdio return -EIO when device communication
|
||||
is not possible
|
||||
|
||||
The bus interface functions txctl and rxctl may be used while the device
|
||||
can not be accessed, eg. upon driver .remove() callback. This patch will
|
||||
immediately return -EIO when this is the case which speeds up the module
|
||||
unload.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
|
||||
@@ -988,6 +988,7 @@ static void brcmf_sdiod_freezer_detach(s
|
||||
|
||||
static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
|
||||
{
|
||||
+ sdiodev->state = BRCMF_SDIOD_DOWN;
|
||||
if (sdiodev->bus) {
|
||||
brcmf_sdio_remove(sdiodev->bus);
|
||||
sdiodev->bus = NULL;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
|
||||
@@ -2820,6 +2820,8 @@ static int brcmf_sdio_bus_txdata(struct
|
||||
struct brcmf_sdio *bus = sdiodev->bus;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len);
|
||||
+ if (sdiodev->state != BRCMF_SDIOD_DATA)
|
||||
+ return -EIO;
|
||||
|
||||
/* Add space for the header */
|
||||
skb_push(pkt, bus->tx_hdrlen);
|
||||
@@ -2948,6 +2950,8 @@ brcmf_sdio_bus_txctl(struct device *dev,
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
+ if (sdiodev->state != BRCMF_SDIOD_DATA)
|
||||
+ return -EIO;
|
||||
|
||||
/* Send from dpc */
|
||||
bus->ctrl_frame_buf = msg;
|
||||
@@ -3238,6 +3242,8 @@ brcmf_sdio_bus_rxctl(struct device *dev,
|
||||
struct brcmf_sdio *bus = sdiodev->bus;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
+ if (sdiodev->state != BRCMF_SDIOD_DATA)
|
||||
+ return -EIO;
|
||||
|
||||
/* Wait until control frame is available */
|
||||
timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending);
|
Loading…
Reference in a new issue