mac80211: add pending brcmfmac patches fixing multiple interfaces
[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;