diff options
author | Arend van Spriel <arend@broadcom.com> | 2013-04-03 12:40:33 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-03 15:07:04 -0400 |
commit | fba1400a9b8149b3c7ee02be3b1ea0429912372e (patch) | |
tree | ea9912614123763ca8e26e74c629b85f77c7a53c /drivers/net/wireless/brcm80211 | |
parent | 43fa635e16c0674c9248b7feb271084c2874bb0a (diff) | |
download | op-kernel-dev-fba1400a9b8149b3c7ee02be3b1ea0429912372e.zip op-kernel-dev-fba1400a9b8149b3c7ee02be3b1ea0429912372e.tar.gz |
brcmfmac: add firmware-signalling cleanup function
Add a cleanup function releasing any queued packet buffers in
the mac descriptor entries.
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Piotr Haber <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 542a971..69f460b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -197,6 +197,7 @@ struct brcmf_fws_info { struct brcmf_pub *drvr; struct brcmf_fws_stats stats; struct brcmf_fws_mac_descriptor nodes[BRCMF_FWS_MAC_DESC_TABLE_SIZE]; + struct brcmf_fws_mac_descriptor other; int fifo_credit[NL80211_NUM_ACS+1+1]; }; @@ -264,6 +265,38 @@ brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea) return ERR_PTR(-ENOENT); } +static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_mac_descriptor *entry, + bool (*fn)(struct sk_buff *, void *), + int ifidx) +{ + brcmf_dbg(TRACE, "enter: entry=(ea=%pM,ifid=%d), ifidx=%d\n", + entry->ea, entry->interface_id, ifidx); + if (entry->occupied && (fn == NULL || (ifidx == entry->interface_id))) { + brcmf_dbg(TRACE, "flush delayQ: ifidx=%d, qlen=%d\n", + ifidx, entry->psq.len); + /* release packets held in DELAYQ */ + brcmu_pktq_flush(&entry->psq, true, fn, &ifidx); + entry->occupied = !!(entry->psq.len); + } +} + +static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx) +{ + int i; + struct brcmf_fws_mac_descriptor *table; + + brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); + if (fws == NULL) + return; + + /* cleanup individual nodes */ + table = &fws->nodes[0]; + for (i = 0; i < ARRAY_SIZE(fws->nodes); i++) + brcmf_fws_mac_desc_cleanup(&table[i], NULL, ifidx); + + brcmf_fws_mac_desc_cleanup(&fws->other, NULL, ifidx); +} + static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi) { brcmf_dbg(CTL, "rssi %d\n", rssi); @@ -394,12 +427,12 @@ int brcmf_fws_init(struct brcmf_pub *drvr) goto fail; } - /* set linkage back */ - drvr->fws->drvr = drvr; - /* create debugfs file for statistics */ brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats); + /* set linkage back */ + drvr->fws->drvr = drvr; + /* TODO: remove upon feature delivery */ brcmf_err("%s bdcv2 tlv signaling [%x]\n", drvr->fw_signals ? "enabled" : "disabled", tlv); @@ -414,9 +447,17 @@ fail: void brcmf_fws_deinit(struct brcmf_pub *drvr) { - /* free top structure */ - kfree(drvr->fws); + struct brcmf_fws_info *fws = drvr->fws; + ulong flags; + + /* cleanup */ + brcmf_fws_lock(drvr, flags); + brcmf_fws_cleanup(fws, -1); drvr->fws = NULL; + brcmf_fws_unlock(drvr, flags); + + /* free top structure */ + kfree(fws); } int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, |