From: Rafał Miłecki Date: Mon, 26 Sep 2016 10:57:18 +0000 (+0200) Subject: mac80211: brcmfmac: fix memleak and add size optimization X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fstaging%2Frmilecki.git;a=commitdiff_plain;h=730dbc9d444cec219304a03c4a1bfe2937276390 mac80211: brcmfmac: fix memleak and add size optimization Signed-off-by: Rafał Miłecki --- diff --git a/package/kernel/mac80211/patches/855-0001-brcmfmac-fix-memory-leak-in-brcmf_fill_bss_param.patch b/package/kernel/mac80211/patches/855-0001-brcmfmac-fix-memory-leak-in-brcmf_fill_bss_param.patch new file mode 100644 index 00000000000..c5ad551eeff --- /dev/null +++ b/package/kernel/mac80211/patches/855-0001-brcmfmac-fix-memory-leak-in-brcmf_fill_bss_param.patch @@ -0,0 +1,43 @@ +From b96a5398abb102cda75abb642b247a061e1b1358 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 21 Sep 2016 07:42:32 +0200 +Subject: [PATCH] brcmfmac: fix memory leak in brcmf_fill_bss_param +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This function is called from get_station callback which means that every +time user space was getting/dumping station(s) we were leaking 2 KiB. + +Signed-off-by: Rafał Miłecki +Fixes: 1f0dc59a6de ("brcmfmac: rework .get_station() callback") +Cc: stable@vger.kernel.org # 4.2+ +--- +Kalle, ideally this should go as 4.8 fix, but I'm aware it's quite late. +If you are not planning to send another pull request, just get it for +the next release and let's let stable guys backport it. +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2529,7 +2529,7 @@ static void brcmf_fill_bss_param(struct + WL_BSS_INFO_MAX); + if (err) { + brcmf_err("Failed to get bss info (%d)\n", err); +- return; ++ goto out_kfree; + } + si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); + si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); +@@ -2541,6 +2541,9 @@ static void brcmf_fill_bss_param(struct + si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; + if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) + si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; ++ ++out_kfree: ++ kfree(buf); + } + + static s32 diff --git a/package/kernel/mac80211/patches/855-0002-brcmfmac-drop-unused-fields-from-struct-brcmf_pub.patch b/package/kernel/mac80211/patches/855-0002-brcmfmac-drop-unused-fields-from-struct-brcmf_pub.patch new file mode 100644 index 00000000000..6fa4f9791c2 --- /dev/null +++ b/package/kernel/mac80211/patches/855-0002-brcmfmac-drop-unused-fields-from-struct-brcmf_pub.patch @@ -0,0 +1,68 @@ +From 9ef5e87962eb35d7e03809266b1a5a1aafd3c7d3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 23 Sep 2016 15:24:58 +0200 +Subject: [PATCH] brcmfmac: drop unused fields from struct brcmf_pub +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +They seem to be there from the first day. We calculate these values but +never use them. + +Signed-off-by: Rafał Miłecki +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 3 --- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h | 4 ---- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c | 2 -- + 3 files changed, 9 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +index 65e8c87..27cd50a 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -519,9 +519,6 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) + ndev->needed_headroom += drvr->hdrlen; + ndev->ethtool_ops = &brcmf_ethtool_ops; + +- drvr->rxsz = ndev->mtu + ndev->hard_header_len + +- drvr->hdrlen; +- + /* set the mac address */ + memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN); + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +index 8fa34ca..f16cfc9 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +@@ -112,15 +112,11 @@ struct brcmf_pub { + + /* Internal brcmf items */ + uint hdrlen; /* Total BRCMF header length (proto + bus) */ +- uint rxsz; /* Rx buffer size bus module should use */ + + /* Dongle media info */ + char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN]; + u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ + +- /* Multicast data packets sent to dongle */ +- unsigned long tx_multicast; +- + struct mac_address addresses[BRCMF_MAX_IFS]; + + struct brcmf_if *iflist[BRCMF_MAX_IFS]; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +index 9f9024a..a190f53 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +@@ -2104,8 +2104,6 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) + if ((skb->priority == 0) || (skb->priority > 7)) + skb->priority = cfg80211_classify8021d(skb, NULL); + +- drvr->tx_multicast += !!multicast; +- + if (fws->avoid_queueing) { + rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb); + if (rc < 0) +-- +2.9.3 + diff --git a/package/kernel/mac80211/patches/855-0003-brcmfmac-initialize-fws-ignal-for-BCDC-protocol-only.patch b/package/kernel/mac80211/patches/855-0003-brcmfmac-initialize-fws-ignal-for-BCDC-protocol-only.patch new file mode 100644 index 00000000000..df8396237e0 --- /dev/null +++ b/package/kernel/mac80211/patches/855-0003-brcmfmac-initialize-fws-ignal-for-BCDC-protocol-only.patch @@ -0,0 +1,135 @@ +From 8931da16a3cb2e0646b1430a9fd94c0a6a5bfd41 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 24 Sep 2016 22:06:31 +0200 +Subject: [PATCH 1/2] brcmfmac: initialize fws(ignal) for BCDC protocol only +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There are two protocols used by Broadcom FullMAC devices: BCDC and +msgbuf. They use different ways for (some part of) communication with +the firmware. Firmware Signaling is required for the first one only +(BCDC). + +So far we were always initializing fws and always calling it's skb +processing function. It was fws that was passing skb processing to the +protocol specific function. It was redundant for the msgbuf case. + +Simply taking few lines of code out of fws allows us to totally avoid +using it. This simplifies code flow, saves some memory & will allow +further optimizations like not compiling fwsignal.c. + +Signed-off-by: Rafał Miłecki +--- + .../wireless/broadcom/brcm80211/brcmfmac/core.c | 24 ++++++++++++++++------ + .../broadcom/brcm80211/brcmfmac/fwsignal.c | 17 ++++++--------- + .../broadcom/brcm80211/brcmfmac/fwsignal.h | 1 + + 3 files changed, 25 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +index 27cd50a..bc3d8ab 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -250,7 +250,17 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, + if (eh->h_proto == htons(ETH_P_PAE)) + atomic_inc(&ifp->pend_8021x_cnt); + +- ret = brcmf_fws_process_skb(ifp, skb); ++ /* determine the priority */ ++ if (skb->priority == 0 || skb->priority > 7) ++ skb->priority = cfg80211_classify8021d(skb, NULL); ++ ++ if (drvr->fws && brcmf_fws_skbs_queueing(drvr->fws)) { ++ ret = brcmf_fws_process_skb(ifp, skb); ++ } else { ++ ret = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb); ++ if (ret < 0) ++ brcmf_txfinalize(ifp, skb, false); ++ } + + done: + if (ret) { +@@ -405,7 +415,7 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) + struct brcmf_if *ifp; + + /* await txstatus signal for firmware if active */ +- if (brcmf_fws_fc_active(drvr->fws)) { ++ if (drvr->fws && brcmf_fws_fc_active(drvr->fws)) { + if (!success) + brcmf_fws_bustxfail(drvr->fws, txp); + } else { +@@ -1006,11 +1016,13 @@ int brcmf_bus_start(struct device *dev) + } + brcmf_feat_attach(drvr); + +- ret = brcmf_fws_init(drvr); +- if (ret < 0) +- goto fail; ++ if (bus_if->proto_type == BRCMF_PROTO_BCDC) { ++ ret = brcmf_fws_init(drvr); ++ if (ret < 0) ++ goto fail; + +- brcmf_fws_add_interface(ifp); ++ brcmf_fws_add_interface(ifp); ++ } + + drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev, + drvr->settings->p2p_enable); +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +index a190f53..495eaf8 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +@@ -2100,16 +2100,6 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) + int rc = 0; + + brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto)); +- /* determine the priority */ +- if ((skb->priority == 0) || (skb->priority > 7)) +- skb->priority = cfg80211_classify8021d(skb, NULL); +- +- if (fws->avoid_queueing) { +- rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb); +- if (rc < 0) +- brcmf_txfinalize(ifp, skb, false); +- return rc; +- } + + /* set control buffer information */ + skcb->if_flags = 0; +@@ -2155,7 +2145,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp) + struct brcmf_fws_info *fws = ifp->drvr->fws; + struct brcmf_fws_mac_descriptor *entry; + +- if (!ifp->ndev) ++ if (!fws || !ifp->ndev) + return; + + entry = &fws->desc.iface[ifp->ifidx]; +@@ -2442,6 +2432,11 @@ void brcmf_fws_deinit(struct brcmf_pub *drvr) + kfree(fws); + } + ++bool brcmf_fws_skbs_queueing(struct brcmf_fws_info *fws) ++{ ++ return !fws->avoid_queueing; ++} ++ + bool brcmf_fws_fc_active(struct brcmf_fws_info *fws) + { + if (!fws->creditmap_received) +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +index ef0ad85..8f7c1d7 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +@@ -20,6 +20,7 @@ + + int brcmf_fws_init(struct brcmf_pub *drvr); + void brcmf_fws_deinit(struct brcmf_pub *drvr); ++bool brcmf_fws_skbs_queueing(struct brcmf_fws_info *fws); + bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); + void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb); + int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb); +-- +2.9.3 + diff --git a/package/kernel/mac80211/patches/855-0004-brcmfmac-compile-fws-ignal-code-only-with-BCDC-suppo.patch b/package/kernel/mac80211/patches/855-0004-brcmfmac-compile-fws-ignal-code-only-with-BCDC-suppo.patch new file mode 100644 index 00000000000..e39d27f435a --- /dev/null +++ b/package/kernel/mac80211/patches/855-0004-brcmfmac-compile-fws-ignal-code-only-with-BCDC-suppo.patch @@ -0,0 +1,112 @@ +From 8708697ab5f203f095b551c5f4abd0d9517498ef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 24 Sep 2016 22:35:47 +0200 +Subject: [PATCH 2/2] brcmfmac: compile fws(ignal) code only with BCDC support + enabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's not needed by the other (msgbuf) protocol, so let's save some size +and compile it conditionally. + +Signed-off-by: Rafał Miłecki +--- + .../wireless/broadcom/brcm80211/brcmfmac/Makefile | 4 +- + .../broadcom/brcm80211/brcmfmac/fwsignal.h | 59 ++++++++++++++++++++++ + 2 files changed, 61 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile +@@ -27,7 +27,6 @@ brcmfmac-objs += \ + chip.o \ + fwil.o \ + fweh.o \ +- fwsignal.o \ + p2p.o \ + proto.o \ + common.o \ +@@ -37,7 +36,8 @@ brcmfmac-objs += \ + btcoex.o \ + vendor.o + brcmfmac-$(CPTCFG_BRCMFMAC_PROTO_BCDC) += \ +- bcdc.o ++ bcdc.o \ ++ fwsignal.o + brcmfmac-$(CPTCFG_BRCMFMAC_PROTO_MSGBUF) += \ + commonring.o \ + flowring.o \ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +@@ -18,6 +18,7 @@ + #ifndef FWSIGNAL_H_ + #define FWSIGNAL_H_ + ++#ifdef CPTCFG_BRCMFMAC_PROTO_BCDC + int brcmf_fws_init(struct brcmf_pub *drvr); + void brcmf_fws_deinit(struct brcmf_pub *drvr); + bool brcmf_fws_skbs_queueing(struct brcmf_fws_info *fws); +@@ -31,5 +32,63 @@ void brcmf_fws_del_interface(struct brcm + void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb); + void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked); + void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb); ++#else ++static inline int brcmf_fws_init(struct brcmf_pub *drvr) ++{ ++ return -ENOTSUPP; ++} ++ ++static inline void brcmf_fws_deinit(struct brcmf_pub *drvr) ++{ ++} ++ ++static inline bool brcmf_fws_skbs_queueing(struct brcmf_fws_info *fws) ++{ ++ return false; ++} ++ ++static inline bool brcmf_fws_fc_active(struct brcmf_fws_info *fws) ++{ ++ return false; ++} ++ ++static inline void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, ++ struct sk_buff *skb) ++{ ++} ++ ++static inline int brcmf_fws_process_skb(struct brcmf_if *ifp, ++ struct sk_buff *skb) ++{ ++ return -ENOTSUPP; ++} ++ ++static inline void brcmf_fws_reset_interface(struct brcmf_if *ifp) ++{ ++} ++ ++static inline void brcmf_fws_add_interface(struct brcmf_if *ifp) ++{ ++} ++ ++static inline void brcmf_fws_del_interface(struct brcmf_if *ifp) ++{ ++} ++ ++static inline void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, ++ struct sk_buff *skb) ++{ ++} ++ ++static inline void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, ++ bool flow_blocked) ++{ ++} ++ ++static inline void brcmf_fws_rxreorder(struct brcmf_if *ifp, ++ struct sk_buff *skb) ++{ ++} ++#endif + + #endif /* FWSIGNAL_H_ */ diff --git a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch index ae571c99ab1..3c8ac3c65dc 100644 --- a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch +++ b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch @@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -1213,6 +1213,7 @@ int __init brcmf_core_init(void) +@@ -1222,6 +1222,7 @@ int __init brcmf_core_init(void) { if (!schedule_work(&brcmf_driver_work)) return -EBUSY; diff --git a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch index f301fe1e4e7..7426c5e6f63 100644 --- a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch +++ b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2783,6 +2783,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip +@@ -2786,6 +2786,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip * preference in cfg struct to apply this to * FW later while initializing the dongle */