mac80211: add pending brcmfmac patches fixing multiple interfaces
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / 330-brcmfmac-introduce-brcmf_net_detach-function.patch
1 From: Arend van Spriel <arend@broadcom.com>
2 Date: Wed, 26 Aug 2015 22:15:04 +0200
3 Subject: [PATCH] brcmfmac: introduce brcmf_net_detach() function
4
5 In case of error during brcmf_bus_start() the network interfaces were
6 freed using free_netdev(). However, the interfaces may have additional
7 memory allocated which is not freed. The netdev has destructor set to
8 brcmf_cfg80211_free_netdev() which frees the additional memory if
9 allocated and call free_netdev(). The brcmf_net_detach() either calls
10 brcmf_cfg80211_free_netdev() directly or uses unregister_netdev() when
11 struct net_device::reg_state indicates the netdev was registered.
12
13 Reported-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
14 Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
15 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
16 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
17 Signed-off-by: Arend van Spriel <arend@broadcom.com>
18 ---
19
20 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
21 +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
22 @@ -4747,7 +4747,8 @@ void brcmf_cfg80211_free_netdev(struct n
23 ifp = netdev_priv(ndev);
24 vif = ifp->vif;
25
26 - brcmf_free_vif(vif);
27 + if (vif)
28 + brcmf_free_vif(vif);
29 free_netdev(ndev);
30 }
31
32 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
33 +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
34 @@ -718,8 +718,6 @@ int brcmf_net_attach(struct brcmf_if *if
35 }
36
37 brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
38 -
39 - ndev->destructor = brcmf_cfg80211_free_netdev;
40 return 0;
41
42 fail:
43 @@ -729,6 +727,14 @@ fail:
44 return -EBADE;
45 }
46
47 +static void brcmf_net_detach(struct net_device *ndev)
48 +{
49 + if (ndev->reg_state == NETREG_REGISTERED)
50 + unregister_netdev(ndev);
51 + else
52 + brcmf_cfg80211_free_netdev(ndev);
53 +}
54 +
55 static int brcmf_net_p2p_open(struct net_device *ndev)
56 {
57 brcmf_dbg(TRACE, "Enter\n");
58 @@ -805,8 +811,7 @@ struct brcmf_if *brcmf_add_if(struct brc
59 ifp->ndev->name);
60 if (ifidx) {
61 netif_stop_queue(ifp->ndev);
62 - unregister_netdev(ifp->ndev);
63 - free_netdev(ifp->ndev);
64 + brcmf_net_detach(ifp->ndev);
65 drvr->iflist[bssidx] = NULL;
66 } else {
67 brcmf_err("ignore IF event\n");
68 @@ -828,6 +833,7 @@ struct brcmf_if *brcmf_add_if(struct brc
69 if (!ndev)
70 return ERR_PTR(-ENOMEM);
71
72 + ndev->destructor = brcmf_cfg80211_free_netdev;
73 ifp = netdev_priv(ndev);
74 ifp->ndev = ndev;
75 /* store mapping ifidx to bssidx */
76 @@ -879,8 +885,7 @@ static void brcmf_del_if(struct brcmf_pu
77 cancel_work_sync(&ifp->setmacaddr_work);
78 cancel_work_sync(&ifp->multicast_work);
79 }
80 - /* unregister will take care of freeing it */
81 - unregister_netdev(ifp->ndev);
82 + brcmf_net_detach(ifp->ndev);
83 }
84 }
85
86 @@ -1056,11 +1061,11 @@ fail:
87 brcmf_fws_deinit(drvr);
88 }
89 if (drvr->iflist[0]) {
90 - free_netdev(ifp->ndev);
91 + brcmf_net_detach(ifp->ndev);
92 drvr->iflist[0] = NULL;
93 }
94 if (p2p_ifp) {
95 - free_netdev(p2p_ifp->ndev);
96 + brcmf_net_detach(p2p_ifp->ndev);
97 drvr->iflist[1] = NULL;
98 }
99 return ret;