mac80211: brcmfmac: fix memleak and add size optimization
authorRafał Miłecki <rafal@milecki.pl>
Mon, 26 Sep 2016 10:57:18 +0000 (12:57 +0200)
committerRafał Miłecki <rafal@milecki.pl>
Mon, 26 Sep 2016 11:46:32 +0000 (13:46 +0200)
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
package/kernel/mac80211/patches/855-0001-brcmfmac-fix-memory-leak-in-brcmf_fill_bss_param.patch [new file with mode: 0644]
package/kernel/mac80211/patches/855-0002-brcmfmac-drop-unused-fields-from-struct-brcmf_pub.patch [new file with mode: 0644]
package/kernel/mac80211/patches/855-0003-brcmfmac-initialize-fws-ignal-for-BCDC-protocol-only.patch [new file with mode: 0644]
package/kernel/mac80211/patches/855-0004-brcmfmac-compile-fws-ignal-code-only-with-BCDC-suppo.patch [new file with mode: 0644]
package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch
package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch

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 (file)
index 0000000..c5ad551
--- /dev/null
@@ -0,0 +1,43 @@
+From b96a5398abb102cda75abb642b247a061e1b1358 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Wed, 21 Sep 2016 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 <rafal@milecki.pl>
+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 (file)
index 0000000..6fa4f97
--- /dev/null
@@ -0,0 +1,68 @@
+From 9ef5e87962eb35d7e03809266b1a5a1aafd3c7d3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 23 Sep 2016 15: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 <rafal@milecki.pl>
+---
+ 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 (file)
index 0000000..df83962
--- /dev/null
@@ -0,0 +1,135 @@
+From 8931da16a3cb2e0646b1430a9fd94c0a6a5bfd41 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+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 <rafal@milecki.pl>
+---
+ .../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 (file)
index 0000000..e39d27f
--- /dev/null
@@ -0,0 +1,112 @@
+From 8708697ab5f203f095b551c5f4abd0d9517498ef Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+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 <rafal@milecki.pl>
+---
+ .../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_ */
index ae571c99ab151245355d0080a6475bcabbb9a2fb..3c8ac3c65dcb2fb6dce1d4d7a731455060615e5f 100644 (file)
@@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -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;
index f301fe1e4e7daa2cabd73aaf869327e2a0fb7d22..7426c5e6f639b83da08393f7108ba85b482b8b5d 100644 (file)
@@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
 
 --- 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
         */