ath9k: revert temperature compensation support patch (FS#111)
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / 319-0001-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch
1 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
2 Date: Fri, 17 Jun 2016 12:29:21 +0200
3 Subject: [PATCH] brcmfmac: fix lockup when removing P2P interface after
4 event timeout
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Removing P2P interface is handled by sending a proper request to the
10 firmware. On success firmware triggers an event and driver's handler
11 removes a matching interface.
12
13 However on event timeout we remove interface directly from the cfg80211
14 callback. Current code doesn't handle this case correctly as it always
15 assumes rtnl to be unlocked.
16
17 Fix it by adding an extra rtnl_locked parameter to functions and calling
18 unregister_netdevice when needed.
19
20 Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
21 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
22 ---
23
24 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
25 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
26 @@ -548,12 +548,16 @@ fail:
27 return -EBADE;
28 }
29
30 -static void brcmf_net_detach(struct net_device *ndev)
31 +static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked)
32 {
33 - if (ndev->reg_state == NETREG_REGISTERED)
34 - unregister_netdev(ndev);
35 - else
36 + if (ndev->reg_state == NETREG_REGISTERED) {
37 + if (rtnl_locked)
38 + unregister_netdevice(ndev);
39 + else
40 + unregister_netdev(ndev);
41 + } else {
42 brcmf_cfg80211_free_netdev(ndev);
43 + }
44 }
45
46 void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
47 @@ -651,7 +655,7 @@ struct brcmf_if *brcmf_add_if(struct brc
48 brcmf_err("ERROR: netdev:%s already exists\n",
49 ifp->ndev->name);
50 netif_stop_queue(ifp->ndev);
51 - brcmf_net_detach(ifp->ndev);
52 + brcmf_net_detach(ifp->ndev, false);
53 drvr->iflist[bsscfgidx] = NULL;
54 } else {
55 brcmf_dbg(INFO, "netdev:%s ignore IF event\n",
56 @@ -699,7 +703,8 @@ struct brcmf_if *brcmf_add_if(struct brc
57 return ifp;
58 }
59
60 -static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx)
61 +static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx,
62 + bool rtnl_locked)
63 {
64 struct brcmf_if *ifp;
65
66 @@ -729,7 +734,7 @@ static void brcmf_del_if(struct brcmf_pu
67 cancel_work_sync(&ifp->multicast_work);
68 cancel_work_sync(&ifp->ndoffload_work);
69 }
70 - brcmf_net_detach(ifp->ndev);
71 + brcmf_net_detach(ifp->ndev, rtnl_locked);
72 } else {
73 /* Only p2p device interfaces which get dynamically created
74 * end up here. In this case the p2p module should be informed
75 @@ -743,14 +748,14 @@ static void brcmf_del_if(struct brcmf_pu
76 }
77 }
78
79 -void brcmf_remove_interface(struct brcmf_if *ifp)
80 +void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked)
81 {
82 if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp))
83 return;
84 brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", ifp->bsscfgidx,
85 ifp->ifidx);
86 brcmf_fws_del_interface(ifp);
87 - brcmf_del_if(ifp->drvr, ifp->bsscfgidx);
88 + brcmf_del_if(ifp->drvr, ifp->bsscfgidx, rtnl_locked);
89 }
90
91 #ifdef CONFIG_INET
92 @@ -1057,9 +1062,9 @@ fail:
93 brcmf_fws_deinit(drvr);
94 }
95 if (ifp)
96 - brcmf_net_detach(ifp->ndev);
97 + brcmf_net_detach(ifp->ndev, false);
98 if (p2p_ifp)
99 - brcmf_net_detach(p2p_ifp->ndev);
100 + brcmf_net_detach(p2p_ifp->ndev, false);
101 drvr->iflist[0] = NULL;
102 drvr->iflist[1] = NULL;
103 if (drvr->settings->ignore_probe_fail)
104 @@ -1128,7 +1133,7 @@ void brcmf_detach(struct device *dev)
105
106 /* make sure primary interface removed last */
107 for (i = BRCMF_MAX_IFS-1; i > -1; i--)
108 - brcmf_remove_interface(drvr->iflist[i]);
109 + brcmf_remove_interface(drvr->iflist[i], false);
110
111 brcmf_cfg80211_detach(drvr->config);
112
113 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
114 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
115 @@ -216,7 +216,7 @@ struct brcmf_if *brcmf_get_ifp(struct br
116 int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
117 struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
118 bool is_p2pdev, char *name, u8 *mac_addr);
119 -void brcmf_remove_interface(struct brcmf_if *ifp);
120 +void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked);
121 void brcmf_txflowblock_if(struct brcmf_if *ifp,
122 enum brcmf_netif_stop_reason reason, bool state);
123 void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
124 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
125 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
126 @@ -183,7 +183,7 @@ static void brcmf_fweh_handle_if_event(s
127 err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
128
129 if (ifp && ifevent->action == BRCMF_E_IF_DEL)
130 - brcmf_remove_interface(ifp);
131 + brcmf_remove_interface(ifp, false);
132 }
133
134 /**
135 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
136 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
137 @@ -2289,7 +2289,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
138 err = 0;
139 }
140 if (err)
141 - brcmf_remove_interface(vif->ifp);
142 + brcmf_remove_interface(vif->ifp, true);
143
144 brcmf_cfg80211_arm_vif_event(cfg, NULL);
145 if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
146 @@ -2395,7 +2395,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_i
147 if (vif != NULL) {
148 brcmf_p2p_cancel_remain_on_channel(vif->ifp);
149 brcmf_p2p_deinit_discovery(p2p);
150 - brcmf_remove_interface(vif->ifp);
151 + brcmf_remove_interface(vif->ifp, false);
152 }
153 /* just set it all to zero */
154 memset(p2p, 0, sizeof(*p2p));